Index: include/__functional_base =================================================================== --- include/__functional_base +++ include/__functional_base @@ -371,6 +371,15 @@ #endif }; +#if _LIBCPP_STD_VER > 17 +template +inline _LIBCPP_INLINE_VISIBILITY +_Tp& __lvref_bind(_Tp& r) _NOEXCEPT { return r; } + +template +_Tp& __lvref_bind(_Tp&& r) = delete; +#endif + template class _LIBCPP_TEMPLATE_VIS reference_wrapper : public __weak_result_type<_Tp> @@ -383,11 +392,22 @@ public: // construct/copy/destroy +#if _LIBCPP_STD_VER > 17 + template , reference_wrapper>::value + >, class = typename __void_t< + decltype(_VSTD::__lvref_bind<_Tp>(_VSTD::declval<_Up>())) + >::type> + _LIBCPP_INLINE_VISIBILITY reference_wrapper(_Up&& __u) + _NOEXCEPT_(noexcept(_VSTD::__lvref_bind<_Tp>(_VSTD::forward<_Up>(__u)))) + : __f_(_VSTD::addressof(_VSTD::__lvref_bind<_Tp>(_VSTD::forward<_Up>(__u)))) {} +#else _LIBCPP_INLINE_VISIBILITY reference_wrapper(type& __f) _NOEXCEPT : __f_(_VSTD::addressof(__f)) {} #ifndef _LIBCPP_CXX03_LANG private: reference_wrapper(type&&); public: // = delete; // do not bind to temps #endif +#endif // access _LIBCPP_INLINE_VISIBILITY operator type& () const _NOEXCEPT {return *__f_;} @@ -509,6 +529,10 @@ #endif // _LIBCPP_CXX03_LANG }; +#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES +template +reference_wrapper(_Tp&) -> reference_wrapper<_Tp>; +#endif template inline _LIBCPP_INLINE_VISIBILITY Index: test/std/utilities/function.objects/refwrap/refwrap.assign/copy_assign.pass.cpp =================================================================== --- test/std/utilities/function.objects/refwrap/refwrap.assign/copy_assign.pass.cpp +++ test/std/utilities/function.objects/refwrap/refwrap.assign/copy_assign.pass.cpp @@ -20,6 +20,12 @@ { }; +struct convertible_to_int_ref { + int val = 0; + operator int&() { return val; } + operator int const&() const { return val; } +}; + template void test(T& t) @@ -54,4 +60,11 @@ test(i); const int j = 0; test(j); + +#if TEST_STD_VER > 17 + convertible_to_int_ref convi; + test(convi); + convertible_to_int_ref const convic; + test(convic); +#endif } Index: test/std/utilities/function.objects/refwrap/refwrap.const/type_conv_ctor.fail.cpp =================================================================== --- /dev/null +++ test/std/utilities/function.objects/refwrap/refwrap.const/type_conv_ctor.fail.cpp @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// reference_wrapper + +// template reference_wrapper(U&&); + +// XFAIL: c++98, c++03, c++11, c++14, c++17 + +#include +#include + +struct convertible_to_float_ref { + float val = 0; + operator float const&() const { return val; } +}; + +int main() +{ + convertible_to_float_ref convf; + std::reference_wrapper r(convf); +} Index: test/std/utilities/function.objects/refwrap/refwrap.const/type_conv_ctor.pass.cpp =================================================================== --- /dev/null +++ test/std/utilities/function.objects/refwrap/refwrap.const/type_conv_ctor.pass.cpp @@ -0,0 +1,58 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// reference_wrapper + +// template reference_wrapper(U&&); + +// XFAIL: c++98, c++03, c++11, c++14, c++17 + +#include +#include + +struct convertible_to_int_ref { + int val = 0; + operator int&() { return val; } + operator int const&() const { return val; } +}; + +struct convertible_from_int { + convertible_from_int(int) {} +}; + +void meow(std::reference_wrapper) {} +void meow(convertible_from_int) {} + +int gi; +std::reference_wrapper purr() { return gi; }; + +template +void +test(T& t) +{ + std::reference_wrapper r(t); + assert(&r.get() == &t); +} + +void f() {} + +int main() +{ + convertible_to_int_ref convi; + test(convi); + convertible_to_int_ref const convic; + test(convic); + + { + meow(0); + (true) ? purr() : 0; + } +}