K-ballo updated this revision to Diff 124201. K-ballo edited the summary of this revision. K-ballo added a comment.
Turn fail test into SFINAE based pass test, mark XFAIL for clang. https://reviews.llvm.org/D40259 Files: include/__functional_base include/functional test/std/utilities/function.objects/refwrap/refwrap.assign/copy_assign.pass.cpp test/std/utilities/function.objects/refwrap/refwrap.const/type_conv_ctor.pass.cpp test/std/utilities/function.objects/refwrap/refwrap.const/type_conv_ctor2.pass.cpp test/std/utilities/function.objects/refwrap/refwrap.const/type_ctor.pass.cpp
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 <functional> #include <cassert> +#include <type_traits> class functor1 { @@ -41,4 +42,19 @@ test(i); const int j = 0; test(j); + + { + using Ref = std::reference_wrapper<int>; + static_assert((std::is_constructible<Ref, int&>::value), ""); + static_assert((!std::is_constructible<Ref, int>::value), ""); + static_assert((!std::is_constructible<Ref, int&&>::value), ""); + } + +#if TEST_STD_VER >= 11 + { + using Ref = std::reference_wrapper<int>; + static_assert((std::is_nothrow_constructible<Ref, int&>::value), ""); + static_assert((!std::is_nothrow_constructible<Ref, int>::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. +// +//===----------------------------------------------------------------------===// + +// <functional> + +// reference_wrapper + +// template <class U> +// 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 <functional> +#include <cassert> + +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<int const>; + static_assert((!std::is_constructible<Ref, convertible_to_float_ref>::value), ""); + static_assert((!std::is_constructible<Ref, convertible_to_float_ref const>::value), ""); +} 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. +// +//===----------------------------------------------------------------------===// + +// <functional> + +// reference_wrapper + +// template <class U> +// reference_wrapper(U&&) noexcept(see below); + +// UNSUPPORTED: c++98, c++03 + +#include <functional> +#include <cassert> + +struct convertible_to_int_ref { + int val = 0; + operator int&() { return val; } + operator int const&() const { return val; } +}; + +template <bool IsNothrow> +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<int>) {} +void meow(convertible_from_int) {} + +int gi; +std::reference_wrapper<int> purr() { return gi; }; + +template <class T> +void +test(T& t) +{ + std::reference_wrapper<T> 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<int>; + static_assert((std::is_nothrow_constructible<Ref, nothrow_convertible<true>>::value), ""); + static_assert((!std::is_nothrow_constructible<Ref, nothrow_convertible<false>>::value), ""); + } + + { + meow(0); + (true) ? purr() : 0; + } + +#ifdef __cpp_deduction_guides + { + int i = 0; + std::reference_wrapper ri(i); + static_assert((std::is_same<decltype(ri), std::reference_wrapper<int>>::value), "" ); + const int j = 0; + std::reference_wrapper rj(j); + static_assert((std::is_same<decltype(rj), std::reference_wrapper<const int>>::value), "" ); + } +#endif +} 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 <functional> #include <cassert> +#include <type_traits> class functor1 { }; +struct convertible_to_int_ref { + int val = 0; + operator int&() { return val; } + operator int const&() const { return val; } +}; + template <class T> 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<int>; + static_assert((std::is_assignable<Ref&, int&>::value), ""); + static_assert((!std::is_assignable<Ref&, int>::value), ""); + static_assert((!std::is_assignable<Ref&, int&&>::value), ""); + } +#endif } 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 <class U> + reference_wrapper(U&&) noexcept(see below); reference_wrapper(const reference_wrapper<T>& x) noexcept; // assignment @@ -60,6 +60,9 @@ operator() (ArgTypes&&...) const; }; +template <class T> + reference_wrapper(T&) -> reference_wrapper<T>; + template <class T> reference_wrapper<T> ref(T& t) noexcept; template <class T> void ref(const T&& t) = delete; template <class T> reference_wrapper<T> ref(reference_wrapper<T>t) noexcept; 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 <class _Up, class = typename enable_if< + !is_same<__uncvref_t<_Up>, 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 <class _Tp> +reference_wrapper(_Tp&) -> reference_wrapper<_Tp>; +#endif template <class _Tp> inline _LIBCPP_INLINE_VISIBILITY
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits