Author: ericwf Date: Sun Jun 26 19:40:41 2016 New Revision: 273837 URL: http://llvm.org/viewvc/llvm-project?rev=273837&view=rev Log: Implement P0358r1. Fixes for not_fn.
Modified: libcxx/trunk/include/functional libcxx/trunk/test/std/utilities/function.objects/func.not_fn/not_fn.pass.cpp Modified: libcxx/trunk/include/functional URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/functional?rev=273837&r1=273836&r2=273837&view=diff ============================================================================== --- libcxx/trunk/include/functional (original) +++ libcxx/trunk/include/functional Sun Jun 26 19:40:41 2016 @@ -2618,18 +2618,33 @@ public: template <class ..._Args> _LIBCPP_INLINE_VISIBILITY - auto operator()(_Args&& ...__args) + auto operator()(_Args&& ...__args) & noexcept(noexcept(!_VSTD::invoke(__fd, _VSTD::forward<_Args>(__args)...))) -> decltype(!_VSTD::invoke(__fd, _VSTD::forward<_Args>(__args)...)) { return !_VSTD::invoke(__fd, _VSTD::forward<_Args>(__args)...); } template <class ..._Args> _LIBCPP_INLINE_VISIBILITY - auto operator()(_Args&& ...__args) const + auto operator()(_Args&& ...__args) && + noexcept(noexcept(!_VSTD::invoke(_VSTD::move(__fd), _VSTD::forward<_Args>(__args)...))) + -> decltype(!_VSTD::invoke(_VSTD::move(__fd), _VSTD::forward<_Args>(__args)...)) + { return !_VSTD::invoke(_VSTD::move(__fd), _VSTD::forward<_Args>(__args)...); } + + template <class ..._Args> + _LIBCPP_INLINE_VISIBILITY + auto operator()(_Args&& ...__args) const& noexcept(noexcept(!_VSTD::invoke(__fd, _VSTD::forward<_Args>(__args)...))) -> decltype(!_VSTD::invoke(__fd, _VSTD::forward<_Args>(__args)...)) { return !_VSTD::invoke(__fd, _VSTD::forward<_Args>(__args)...); } + + template <class ..._Args> + _LIBCPP_INLINE_VISIBILITY + auto operator()(_Args&& ...__args) const&& + noexcept(noexcept(!_VSTD::invoke(_VSTD::move(__fd), _VSTD::forward<_Args>(__args)...))) + -> decltype(!_VSTD::invoke(_VSTD::move(__fd), _VSTD::forward<_Args>(__args)...)) + { return !_VSTD::invoke(_VSTD::move(__fd), _VSTD::forward<_Args>(__args)...); } + private: template <class _RawFunc, class = enable_if_t<!is_same<decay_t<_RawFunc>, __not_fn_imp>::value>> Modified: libcxx/trunk/test/std/utilities/function.objects/func.not_fn/not_fn.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/function.objects/func.not_fn/not_fn.pass.cpp?rev=273837&r1=273836&r2=273837&view=diff ============================================================================== --- libcxx/trunk/test/std/utilities/function.objects/func.not_fn/not_fn.pass.cpp (original) +++ libcxx/trunk/test/std/utilities/function.objects/func.not_fn/not_fn.pass.cpp Sun Jun 26 19:40:41 2016 @@ -88,7 +88,6 @@ struct NoExceptCallable { Ret value; }; - struct CopyAssignableWrapper { CopyAssignableWrapper(CopyAssignableWrapper const&) = default; CopyAssignableWrapper(CopyAssignableWrapper&&) = default; @@ -124,32 +123,44 @@ struct MemFunCallable { bool value; }; -enum CallType { +enum CallType : unsigned { CT_None, - CT_Const, - CT_NonConst + CT_NonConst = 1, + CT_Const = 2, + CT_LValue = 4, + CT_RValue = 8 }; +inline constexpr CallType operator|(CallType LHS, CallType RHS) { + return static_cast<CallType>(static_cast<unsigned>(LHS) | static_cast<unsigned>(RHS)); +} + struct ForwardingCallObject { template <class ...Args> bool operator()(Args&&... args) & { - set_call<Args&&...>(CT_NonConst); + set_call<Args&&...>(CT_NonConst | CT_LValue); return true; } template <class ...Args> bool operator()(Args&&... args) const & { - set_call<Args&&...>(CT_Const); + set_call<Args&&...>(CT_Const | CT_LValue); return true; } // Don't allow the call operator to be invoked as an rvalue. template <class ...Args> - bool operator()(Args&&... args) && = delete; + bool operator()(Args&&... args) && { + set_call<Args&&...>(CT_NonConst | CT_RValue); + return true; + } template <class ...Args> - bool operator()(Args&&... args) const && = delete; + bool operator()(Args&&... args) const && { + set_call<Args&&...>(CT_Const | CT_RValue); + return true; + } template <class ...Args> static void set_call(CallType type) { @@ -450,52 +461,82 @@ void call_operator_forwarding_test() const auto& c_obj = obj; { // test zero args obj(); - assert(Fn::check_call<>(CT_NonConst)); + assert(Fn::check_call<>(CT_NonConst | CT_LValue)); + std::move(obj)(); + assert(Fn::check_call<>(CT_NonConst | CT_RValue)); c_obj(); - assert(Fn::check_call<>(CT_Const)); + assert(Fn::check_call<>(CT_Const | CT_LValue)); + std::move(c_obj)(); + assert(Fn::check_call<>(CT_Const | CT_RValue)); } { // test value categories int x = 42; const int cx = 42; obj(x); - assert(Fn::check_call<int&>(CT_NonConst)); + assert(Fn::check_call<int&>(CT_NonConst | CT_LValue)); obj(cx); - assert(Fn::check_call<const int&>(CT_NonConst)); + assert(Fn::check_call<const int&>(CT_NonConst | CT_LValue)); obj(std::move(x)); - assert(Fn::check_call<int&&>(CT_NonConst)); + assert(Fn::check_call<int&&>(CT_NonConst | CT_LValue)); obj(std::move(cx)); - assert(Fn::check_call<const int&&>(CT_NonConst)); + assert(Fn::check_call<const int&&>(CT_NonConst | CT_LValue)); obj(42); - assert(Fn::check_call<int&&>(CT_NonConst)); + assert(Fn::check_call<int&&>(CT_NonConst | CT_LValue)); + } + { // test value categories - rvalue + int x = 42; + const int cx = 42; + std::move(obj)(x); + assert(Fn::check_call<int&>(CT_NonConst | CT_RValue)); + std::move(obj)(cx); + assert(Fn::check_call<const int&>(CT_NonConst | CT_RValue)); + std::move(obj)(std::move(x)); + assert(Fn::check_call<int&&>(CT_NonConst | CT_RValue)); + std::move(obj)(std::move(cx)); + assert(Fn::check_call<const int&&>(CT_NonConst | CT_RValue)); + std::move(obj)(42); + assert(Fn::check_call<int&&>(CT_NonConst | CT_RValue)); } { // test value categories - const call int x = 42; const int cx = 42; c_obj(x); - assert(Fn::check_call<int&>(CT_Const)); + assert(Fn::check_call<int&>(CT_Const | CT_LValue)); c_obj(cx); - assert(Fn::check_call<const int&>(CT_Const)); + assert(Fn::check_call<const int&>(CT_Const | CT_LValue)); c_obj(std::move(x)); - assert(Fn::check_call<int&&>(CT_Const)); + assert(Fn::check_call<int&&>(CT_Const | CT_LValue)); c_obj(std::move(cx)); - assert(Fn::check_call<const int&&>(CT_Const)); + assert(Fn::check_call<const int&&>(CT_Const | CT_LValue)); c_obj(42); - assert(Fn::check_call<int&&>(CT_Const)); + assert(Fn::check_call<int&&>(CT_Const | CT_LValue)); + } + { // test value categories - const call rvalue + int x = 42; + const int cx = 42; + std::move(c_obj)(x); + assert(Fn::check_call<int&>(CT_Const | CT_RValue)); + std::move(c_obj)(cx); + assert(Fn::check_call<const int&>(CT_Const | CT_RValue)); + std::move(c_obj)(std::move(x)); + assert(Fn::check_call<int&&>(CT_Const | CT_RValue)); + std::move(c_obj)(std::move(cx)); + assert(Fn::check_call<const int&&>(CT_Const | CT_RValue)); + std::move(c_obj)(42); + assert(Fn::check_call<int&&>(CT_Const | CT_RValue)); } { // test multi arg int x = 42; const double y = 3.14; std::string s = "abc"; obj(42, std::move(y), s, std::string{"foo"}); - Fn::check_call<int&&, const double&&, std::string&, std::string&&>(CT_NonConst); + Fn::check_call<int&&, const double&&, std::string&, std::string&&>(CT_NonConst | CT_LValue); + std::move(obj)(42, std::move(y), s, std::string{"foo"}); + Fn::check_call<int&&, const double&&, std::string&, std::string&&>(CT_NonConst | CT_RValue); c_obj(42, std::move(y), s, std::string{"foo"}); - Fn::check_call<int&&, const double&&, std::string&, std::string&&>(CT_Const); - } - { // call as rvalue test. This should not invoke the functor as an rvalue. - std::move(obj)(); - assert(Fn::check_call<>(CT_NonConst)); - std::move(c_obj)(); - assert(Fn::check_call<>(CT_Const)); + Fn::check_call<int&&, const double&&, std::string&, std::string&&>(CT_Const | CT_LValue); + std::move(c_obj)(42, std::move(y), s, std::string{"foo"}); + Fn::check_call<int&&, const double&&, std::string&, std::string&&>(CT_Const | CT_RValue); } } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits