diff options
Diffstat (limited to 'libcxx')
| -rw-r--r-- | libcxx/include/functional | 19 | ||||
| -rw-r--r-- | libcxx/test/std/utilities/function.objects/func.not_fn/not_fn.pass.cpp | 97 | 
2 files changed, 86 insertions, 30 deletions
diff --git a/libcxx/include/functional b/libcxx/include/functional index a13772f31ae..581f965b2b8 100644 --- a/libcxx/include/functional +++ b/libcxx/include/functional @@ -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>> diff --git a/libcxx/test/std/utilities/function.objects/func.not_fn/not_fn.pass.cpp b/libcxx/test/std/utilities/function.objects/func.not_fn/not_fn.pass.cpp index 94839957094..c12fa792097 100644 --- a/libcxx/test/std/utilities/function.objects/func.not_fn/not_fn.pass.cpp +++ b/libcxx/test/std/utilities/function.objects/func.not_fn/not_fn.pass.cpp @@ -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);      }  }  | 

