Add implicit conversion between compatible reference wrappers (refs #83)

This commit is contained in:
Peter Dimov
2020-11-19 18:57:56 +02:00
parent 7bc2873e38
commit 54671134ae
5 changed files with 121 additions and 0 deletions

View File

@ -10,6 +10,7 @@
#include <boost/config.hpp>
#include <boost/config/workaround.hpp>
#include <boost/core/addressof.hpp>
#include <boost/core/enable_if.hpp>
//
// 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<Y*>(0) ) ) == sizeof(yes) };
};
struct ref_empty
{
};
} // namespace detail
// reference_wrapper
/**
@ -87,6 +108,14 @@ public:
public:
#endif
template<class Y> friend class reference_wrapper;
template<class Y> reference_wrapper( reference_wrapper<Y> r,
typename enable_if_c<boost::detail::ref_convertible<Y, T>::value,
boost::detail::ref_empty>::type = boost::detail::ref_empty() ): t_( r.t_ )
{
}
/**
@return The stored reference.
@remark Does not throw.

View File

@ -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 ;

View File

@ -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 <boost/ref.hpp>
#include <boost/core/lightweight_test.hpp>
struct X
{
};
struct Y: public X
{
};
void f1( boost::reference_wrapper<X> r, Y * p )
{
BOOST_TEST_EQ( r.get_pointer(), p );
}
void f2( boost::reference_wrapper<int const> 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();
}

View File

@ -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 <boost/ref.hpp>
struct X
{
};
struct Y
{
};
void f( boost::reference_wrapper<X> )
{
}
int main()
{
Y y;
f( boost::ref(y) ); // should fail
}

View File

@ -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 <boost/ref.hpp>
void f( boost::reference_wrapper< int const > )
{
}
int main()
{
long y = 0;
f( boost::ref(y) ); // should fail
}