mirror of
https://github.com/llvm-mirror/libcxx.git
synced 2025-10-23 01:18:52 +08:00
Implement P0358r1. Fixes for not_fn.
git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@273837 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -2618,18 +2618,33 @@ public:
|
|||||||
|
|
||||||
template <class ..._Args>
|
template <class ..._Args>
|
||||||
_LIBCPP_INLINE_VISIBILITY
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
auto operator()(_Args&& ...__args)
|
auto operator()(_Args&& ...__args) &
|
||||||
noexcept(noexcept(!_VSTD::invoke(__fd, _VSTD::forward<_Args>(__args)...)))
|
noexcept(noexcept(!_VSTD::invoke(__fd, _VSTD::forward<_Args>(__args)...)))
|
||||||
-> decltype(!_VSTD::invoke(__fd, _VSTD::forward<_Args>(__args)...))
|
-> decltype(!_VSTD::invoke(__fd, _VSTD::forward<_Args>(__args)...))
|
||||||
{ return !_VSTD::invoke(__fd, _VSTD::forward<_Args>(__args)...); }
|
{ return !_VSTD::invoke(__fd, _VSTD::forward<_Args>(__args)...); }
|
||||||
|
|
||||||
template <class ..._Args>
|
template <class ..._Args>
|
||||||
_LIBCPP_INLINE_VISIBILITY
|
_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)...)))
|
noexcept(noexcept(!_VSTD::invoke(__fd, _VSTD::forward<_Args>(__args)...)))
|
||||||
-> decltype(!_VSTD::invoke(__fd, _VSTD::forward<_Args>(__args)...))
|
-> decltype(!_VSTD::invoke(__fd, _VSTD::forward<_Args>(__args)...))
|
||||||
{ return !_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:
|
private:
|
||||||
template <class _RawFunc,
|
template <class _RawFunc,
|
||||||
class = enable_if_t<!is_same<decay_t<_RawFunc>, __not_fn_imp>::value>>
|
class = enable_if_t<!is_same<decay_t<_RawFunc>, __not_fn_imp>::value>>
|
||||||
|
@@ -88,7 +88,6 @@ struct NoExceptCallable {
|
|||||||
Ret value;
|
Ret value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct CopyAssignableWrapper {
|
struct CopyAssignableWrapper {
|
||||||
CopyAssignableWrapper(CopyAssignableWrapper const&) = default;
|
CopyAssignableWrapper(CopyAssignableWrapper const&) = default;
|
||||||
CopyAssignableWrapper(CopyAssignableWrapper&&) = default;
|
CopyAssignableWrapper(CopyAssignableWrapper&&) = default;
|
||||||
@@ -124,32 +123,44 @@ struct MemFunCallable {
|
|||||||
bool value;
|
bool value;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum CallType {
|
enum CallType : unsigned {
|
||||||
CT_None,
|
CT_None,
|
||||||
CT_Const,
|
CT_NonConst = 1,
|
||||||
CT_NonConst
|
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 {
|
struct ForwardingCallObject {
|
||||||
|
|
||||||
template <class ...Args>
|
template <class ...Args>
|
||||||
bool operator()(Args&&... args) & {
|
bool operator()(Args&&... args) & {
|
||||||
set_call<Args&&...>(CT_NonConst);
|
set_call<Args&&...>(CT_NonConst | CT_LValue);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ...Args>
|
template <class ...Args>
|
||||||
bool operator()(Args&&... args) const & {
|
bool operator()(Args&&... args) const & {
|
||||||
set_call<Args&&...>(CT_Const);
|
set_call<Args&&...>(CT_Const | CT_LValue);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't allow the call operator to be invoked as an rvalue.
|
// Don't allow the call operator to be invoked as an rvalue.
|
||||||
template <class ...Args>
|
template <class ...Args>
|
||||||
bool operator()(Args&&... args) && = delete;
|
bool operator()(Args&&... args) && {
|
||||||
|
set_call<Args&&...>(CT_NonConst | CT_RValue);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
template <class ...Args>
|
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>
|
template <class ...Args>
|
||||||
static void set_call(CallType type) {
|
static void set_call(CallType type) {
|
||||||
@@ -450,52 +461,82 @@ void call_operator_forwarding_test()
|
|||||||
const auto& c_obj = obj;
|
const auto& c_obj = obj;
|
||||||
{ // test zero args
|
{ // test zero args
|
||||||
obj();
|
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();
|
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
|
{ // test value categories
|
||||||
int x = 42;
|
int x = 42;
|
||||||
const int cx = 42;
|
const int cx = 42;
|
||||||
obj(x);
|
obj(x);
|
||||||
assert(Fn::check_call<int&>(CT_NonConst));
|
assert(Fn::check_call<int&>(CT_NonConst | CT_LValue));
|
||||||
obj(cx);
|
obj(cx);
|
||||||
assert(Fn::check_call<const int&>(CT_NonConst));
|
assert(Fn::check_call<const int&>(CT_NonConst | CT_LValue));
|
||||||
obj(std::move(x));
|
obj(std::move(x));
|
||||||
assert(Fn::check_call<int&&>(CT_NonConst));
|
assert(Fn::check_call<int&&>(CT_NonConst | CT_LValue));
|
||||||
obj(std::move(cx));
|
obj(std::move(cx));
|
||||||
assert(Fn::check_call<const int&&>(CT_NonConst));
|
assert(Fn::check_call<const int&&>(CT_NonConst | CT_LValue));
|
||||||
obj(42);
|
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
|
{ // test value categories - const call
|
||||||
int x = 42;
|
int x = 42;
|
||||||
const int cx = 42;
|
const int cx = 42;
|
||||||
c_obj(x);
|
c_obj(x);
|
||||||
assert(Fn::check_call<int&>(CT_Const));
|
assert(Fn::check_call<int&>(CT_Const | CT_LValue));
|
||||||
c_obj(cx);
|
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));
|
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));
|
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);
|
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
|
{ // test multi arg
|
||||||
int x = 42;
|
int x = 42;
|
||||||
const double y = 3.14;
|
const double y = 3.14;
|
||||||
std::string s = "abc";
|
std::string s = "abc";
|
||||||
obj(42, std::move(y), s, std::string{"foo"});
|
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"});
|
c_obj(42, std::move(y), s, std::string{"foo"});
|
||||||
Fn::check_call<int&&, const double&&, std::string&, std::string&&>(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"});
|
||||||
{ // call as rvalue test. This should not invoke the functor as an rvalue.
|
Fn::check_call<int&&, const double&&, std::string&, std::string&&>(CT_Const | CT_RValue);
|
||||||
std::move(obj)();
|
|
||||||
assert(Fn::check_call<>(CT_NonConst));
|
|
||||||
std::move(c_obj)();
|
|
||||||
assert(Fn::check_call<>(CT_Const));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user