diff --git a/include/boost/core/ref.hpp b/include/boost/core/ref.hpp index 79f0b63..147cee2 100644 --- a/include/boost/core/ref.hpp +++ b/include/boost/core/ref.hpp @@ -10,6 +10,7 @@ #include #include #include +#include // // ref.hpp - ref/cref, useful helper functions @@ -46,6 +47,26 @@ namespace boost #endif +namespace detail +{ + +template< class Y, class T > struct ref_convertible +{ + typedef char (&yes) [1]; + typedef char (&no) [2]; + + static yes f( T* ); + static no f( ... ); + + enum _vt { value = sizeof( (f)( static_cast(0) ) ) == sizeof(yes) }; +}; + +struct ref_empty +{ +}; + +} // namespace detail + // reference_wrapper /** @@ -87,6 +108,14 @@ public: public: #endif + template friend class reference_wrapper; + + template reference_wrapper( reference_wrapper r, + typename enable_if_c::value, + boost::detail::ref_empty>::type = boost::detail::ref_empty() ): t_( r.t_ ) + { + } + /** @return The stored reference. @remark Does not throw. diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 6d060d1..0616ecc 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -35,7 +35,10 @@ compile-fail ref_rv_fail4.cpp ; compile-fail ref_rv_fail5.cpp ; compile-fail ref_implicit_fail.cpp ; compile-fail ref_implicit_fail2.cpp ; +compile-fail ref_implicit_fail3.cpp ; +compile-fail ref_implicit_fail4.cpp ; run ref_cv_test.cpp ; +run ref_conversion_test.cpp ; run eif_constructors.cpp ; run eif_dummy_arg_disambiguation.cpp ; diff --git a/test/ref_conversion_test.cpp b/test/ref_conversion_test.cpp new file mode 100644 index 0000000..6c336ca --- /dev/null +++ b/test/ref_conversion_test.cpp @@ -0,0 +1,39 @@ +// Implicit conversions between compatible reference wrappers +// +// Copyright 2020 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include +#include + +struct X +{ +}; + +struct Y: public X +{ +}; + +void f1( boost::reference_wrapper r, Y * p ) +{ + BOOST_TEST_EQ( r.get_pointer(), p ); +} + +void f2( boost::reference_wrapper r, int * p ) +{ + BOOST_TEST_EQ( r.get_pointer(), p ); +} + +int main() +{ + Y y; + f1( boost::ref(y), &y ); + + int i = 0; + f2( boost::ref(i), &i ); + + return boost::report_errors(); +} diff --git a/test/ref_implicit_fail3.cpp b/test/ref_implicit_fail3.cpp new file mode 100644 index 0000000..726feb4 --- /dev/null +++ b/test/ref_implicit_fail3.cpp @@ -0,0 +1,29 @@ +// +// Incompatible reference_wrappers must not implicitly convert to each other +// +// Copyright 2020 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// + +#include + +struct X +{ +}; + +struct Y +{ +}; + +void f( boost::reference_wrapper ) +{ +} + +int main() +{ + Y y; + f( boost::ref(y) ); // should fail +} diff --git a/test/ref_implicit_fail4.cpp b/test/ref_implicit_fail4.cpp new file mode 100644 index 0000000..5f5e0c9 --- /dev/null +++ b/test/ref_implicit_fail4.cpp @@ -0,0 +1,21 @@ +// +// Incompatible reference_wrappers must not implicitly convert to each other +// +// Copyright 2020 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// + +#include + +void f( boost::reference_wrapper< int const > ) +{ +} + +int main() +{ + long y = 0; + f( boost::ref(y) ); // should fail +}