Index: include/__functional_base =================================================================== --- include/__functional_base +++ include/__functional_base @@ -381,12 +381,25 @@ private: type* __f_; + static _LIBCPP_INLINE_VISIBILITY + _Tp& __bind(_Tp& r) _NOEXCEPT { return r; } + +#ifndef _LIBCPP_CXX03_LANG + static _Tp& __bind(_Tp&& r) = delete; +#endif + public: // construct/copy/destroy +#ifndef _LIBCPP_CXX03_LANG + template , reference_wrapper>::value + >::type, class = decltype(__bind(_VSTD::declval<_Up>()))> + _LIBCPP_INLINE_VISIBILITY reference_wrapper(_Up&& __u) + _NOEXCEPT_(noexcept(__bind(_VSTD::forward<_Up>(__u)))) + : __f_(_VSTD::addressof(__bind(_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 // access @@ -509,6 +522,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: include/functional =================================================================== --- include/functional +++ include/functional @@ -43,8 +43,8 @@ typedef see below result_type; // Not always defined // construct/copy/destroy - reference_wrapper(T&) noexcept; - reference_wrapper(T&&) = delete; // do not bind to temps + template + reference_wrapper(U&&) noexcept(see below); reference_wrapper(const reference_wrapper& x) noexcept; // assignment @@ -60,6 +60,9 @@ operator() (ArgTypes&&...) const; }; +template + reference_wrapper(T&) -> reference_wrapper; + template reference_wrapper ref(T& t) noexcept; template void ref(const T&& t) = delete; template reference_wrapper ref(reference_wrappert) noexcept; 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 @@ -15,11 +15,18 @@ #include #include +#include class functor1 { }; +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 +61,18 @@ test(i); const int j = 0; test(j); + +#if TEST_STD_VER >= 11 + convertible_to_int_ref convi; + test(convi); + convertible_to_int_ref const convic; + test(convic); + + { + using Ref = std::reference_wrapper; + static_assert((std::is_assignable::value), ""); + static_assert((!std::is_assignable::value), ""); + static_assert((!std::is_assignable::value), ""); + } +#endif } 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,82 @@ +//===----------------------------------------------------------------------===// +// +// 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&&) noexcept(see below); + +// UNSUPPORTED: c++98, c++03 + +#include +#include + +struct convertible_to_int_ref { + int val = 0; + operator int&() { return val; } + operator int const&() const { return val; } +}; + +template +struct nothrow_convertible { + int val = 0; + operator int&() noexcept(IsNothrow) { 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); + + { + using Ref = std::reference_wrapper; + static_assert((std::is_nothrow_constructible>::value), ""); + static_assert((!std::is_nothrow_constructible>::value), ""); + } + + { + meow(0); + (true) ? purr() : 0; + } + +#ifdef __cpp_deduction_guides + { + int i = 0; + std::reference_wrapper ri(i); + static_assert((std::is_same>::value), "" ); + const int j = 0; + std::reference_wrapper rj(j); + static_assert((std::is_same>::value), "" ); + } +#endif +} Index: test/std/utilities/function.objects/refwrap/refwrap.const/type_conv_ctor2.pass.cpp =================================================================== --- /dev/null +++ test/std/utilities/function.objects/refwrap/refwrap.const/type_conv_ctor2.pass.cpp @@ -0,0 +1,34 @@ +//===----------------------------------------------------------------------===// +// +// 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&&) noexcept(see below); + +// UNSUPPORTED: c++98, c++03 +// XFAIL: clang-3.7, clang-3.8, clang-3.9, clang-4.0, clang-5.0, clang-6.0 + +#include +#include + +struct convertible_to_float_ref { + float val = 0; + operator float const&() { return val; } + operator float const&() const { return val; } +}; + +int main() +{ + using Ref = std::reference_wrapper; + static_assert((!std::is_constructible::value), ""); + static_assert((!std::is_constructible::value), ""); +} Index: test/std/utilities/function.objects/refwrap/refwrap.const/type_ctor.pass.cpp =================================================================== --- test/std/utilities/function.objects/refwrap/refwrap.const/type_ctor.pass.cpp +++ test/std/utilities/function.objects/refwrap/refwrap.const/type_ctor.pass.cpp @@ -15,6 +15,7 @@ #include #include +#include class functor1 { @@ -41,4 +42,19 @@ test(i); const int j = 0; test(j); + + { + using Ref = std::reference_wrapper; + static_assert((std::is_constructible::value), ""); + static_assert((!std::is_constructible::value), ""); + static_assert((!std::is_constructible::value), ""); + } + +#if TEST_STD_VER >= 11 + { + using Ref = std::reference_wrapper; + static_assert((std::is_nothrow_constructible::value), ""); + static_assert((!std::is_nothrow_constructible::value), ""); + } +#endif }