diff --git a/libcxx/include/functional b/libcxx/include/functional --- a/libcxx/include/functional +++ b/libcxx/include/functional @@ -2984,61 +2984,111 @@ return _VSTD::__invoke(_VSTD::forward<_Fn>(__f), _VSTD::forward<_Args>(__args)...); } -template -class _LIBCPP_TEMPLATE_VIS __not_fn_imp { - _DecayFunc __fd; - -public: - __not_fn_imp() = delete; - - template - _LIBCPP_INLINE_VISIBILITY - 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 - _LIBCPP_INLINE_VISIBILITY - 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)...); } +#endif - template - _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)...); } +#if _LIBCPP_STD_VER > 14 +template::value>::type> +struct __perfect_forward_impl; + +template +struct __perfect_forward_impl<_Op, __tuple_types<_Bound...>, __tuple_indices<_Idxs...>> +{ + _VSTD::tuple<_Bound...> __bound; + + template + _LIBCPP_INLINE_VISIBILITY constexpr auto operator()(_Args&&... __args) & + noexcept(noexcept(_Op::__call(_VSTD::get<_Idxs>(__bound)..., _VSTD::forward<_Args>(__args)...))) + -> decltype( _Op::__call(_VSTD::get<_Idxs>(__bound)..., _VSTD::forward<_Args>(__args)...)) + {return _Op::__call(_VSTD::get<_Idxs>(__bound)..., _VSTD::forward<_Args>(__args)...);} + + template + _LIBCPP_INLINE_VISIBILITY constexpr auto operator()(_Args&&... __args) const& + noexcept(noexcept(_Op::__call(_VSTD::get<_Idxs>(__bound)..., _VSTD::forward<_Args>(__args)...))) + -> decltype( _Op::__call(_VSTD::get<_Idxs>(__bound)..., _VSTD::forward<_Args>(__args)...)) + {return _Op::__call(_VSTD::get<_Idxs>(__bound)..., _VSTD::forward<_Args>(__args)...);} + + template + _LIBCPP_INLINE_VISIBILITY constexpr auto operator()(_Args&&... __args) && + noexcept(noexcept(_Op::__call(_VSTD::get<_Idxs>(_VSTD::move(__bound))..., + _VSTD::forward<_Args>(__args)...))) + -> decltype( _Op::__call(_VSTD::get<_Idxs>(_VSTD::move(__bound))..., + _VSTD::forward<_Args>(__args)...)) + {return _Op::__call(_VSTD::get<_Idxs>(_VSTD::move(__bound))..., + _VSTD::forward<_Args>(__args)...);} + + template + _LIBCPP_INLINE_VISIBILITY constexpr auto operator()(_Args&&... __args) const&& + noexcept(noexcept(_Op::__call(_VSTD::get<_Idxs>(_VSTD::move(__bound))..., + _VSTD::forward<_Args>(__args)...))) + -> decltype( _Op::__call(_VSTD::get<_Idxs>(_VSTD::move(__bound))..., + _VSTD::forward<_Args>(__args)...)) + {return _Op::__call(_VSTD::get<_Idxs>(_VSTD::move(__bound))..., + _VSTD::forward<_Args>(__args)...);} + + template>::type, + class = _EnableIf<_VSTD::is_copy_constructible_v<_Fn>>> + __perfect_forward_impl(__perfect_forward_impl const& __other) + : __bound(__other.__bound) {} + + template>::type, + class = _EnableIf<_VSTD::is_move_constructible_v<_Fn>>> + __perfect_forward_impl(__perfect_forward_impl && __other) + : __bound(_VSTD::move(__other.__bound)) {} + + template + explicit constexpr __perfect_forward_impl(_BoundArgs&&... __bound) : + __bound(_VSTD::forward<_BoundArgs>(__bound)...) { } +}; + +template +using __perfect_forward = + __perfect_forward_impl<_Op, __tuple_types...>>; + +struct __not_fn_op +{ + template + static auto __call(_Args&&... __args) + noexcept(noexcept(!_VSTD::invoke(_VSTD::forward<_Args>(__args)...))) + -> decltype( !_VSTD::invoke(_VSTD::forward<_Args>(__args)...)) + { return !_VSTD::invoke(_VSTD::forward<_Args>(__args)...); } +}; + +template, _Fn> && + is_move_constructible_v<_Fn>>> +inline auto not_fn(_Fn&& __f) +{ + return __perfect_forward<__not_fn_op, _Fn> (_VSTD::forward<_Fn>(__f)); +} - template - _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)...); } +#endif // _LIBCPP_STD_VER > 14 -private: - template , __not_fn_imp>::value>> - _LIBCPP_INLINE_VISIBILITY - explicit __not_fn_imp(_RawFunc&& __rf) - : __fd(_VSTD::forward<_RawFunc>(__rf)) {} +#if _LIBCPP_STD_VER > 17 - template - friend inline _LIBCPP_INLINE_VISIBILITY - __not_fn_imp> not_fn(_RawFunc&&); +struct __bind_front_op +{ + template + constexpr static auto __call(_Args&&... __args) + noexcept(noexcept(_VSTD::invoke(_VSTD::forward<_Args>(__args)...))) + -> decltype( _VSTD::invoke(_VSTD::forward<_Args>(__args)...)) + { return _VSTD::invoke(_VSTD::forward<_Args>(__args)...); } }; -template -inline _LIBCPP_INLINE_VISIBILITY -__not_fn_imp> not_fn(_RawFunc&& __fn) { - return __not_fn_imp>(_VSTD::forward<_RawFunc>(__fn)); +template, _Fn>, + is_move_constructible>, + is_constructible, _Args>..., + is_move_constructible<_Args>... + >::value>> +inline constexpr auto bind_front(_Fn&& __f, _Args&&... __args) +{ + return __perfect_forward<__bind_front_op, _Fn, _Args...>(_VSTD::forward<_Fn>(__f), + _VSTD::forward<_Args>(__args)...); } -#endif +#endif // _LIBCPP_STD_VER > 17 // struct hash in diff --git a/libcxx/test/std/utilities/function.objects/func.bind_front/bind_front.pass.cpp b/libcxx/test/std/utilities/function.objects/func.bind_front/bind_front.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/function.objects/func.bind_front/bind_front.pass.cpp @@ -0,0 +1,237 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// functional + +// template unspecified bind_front(F&&, Args&&...); + +#include +#include "callable_types.h" + +int add (int a, int b) { return a + b; } + +int long_test (int a, int b, int c, int d, int e, int f) +{ return a + b + c + d + e + f; } + +struct Foo { int a; int b; }; + +struct FooCall { Foo operator()(int a, int b) { return Foo { a, b }; } }; + +struct S { bool operator()(int a) { return a == 1; } }; + +void basic_tests() +{ + int n = 2; + int m = 1; + + auto a = std::bind_front(add, m, n); + assert(a() == 3); + + auto b = std::bind_front(long_test, m, n, m, m, m, m); + assert(b() == 7); + + auto c = std::bind_front(long_test, n, m); + assert(c(1, 1, 1, 1) == 7); + + auto d = std::bind_front(S{}, m); + assert(d()); + + auto f = std::bind_front(add, n); + assert(f(3) == 5); +} + +struct constexpr_callable +{ + constexpr bool operator()(int, int) { return true; } +}; + +bool constexpr constexpr_test() +{ + constexpr_callable value; + std::bind_front(value, 1); + std::bind_front(std::move(value), 1); + return true; +} + +struct variadic_fn +{ + template + int operator ()(Args&&... args) + { + return sizeof...(args); + } +}; + +void test_variadic() +{ + variadic_fn value; + auto fn = std::bind_front(value, 0, 0, 0); + assert(fn(0, 0, 0) == 6); +} + +struct mutable_callable +{ + bool should_call_const; + + bool operator()(int, int) { assert(!should_call_const); return true; } + bool operator()(int, int) const { assert( should_call_const); return true; } +}; + +void test_mutable() +{ + const mutable_callable v1 { true }; + const auto fn1 = std::bind_front(v1, 0); + assert(fn1(0)); + + mutable_callable v2 { false }; + auto fn2 = std::bind_front(v2, 0); + assert(fn2(0)); +}; + +struct call_member +{ + bool member(int, int) { return true; } +}; + +void test_call_member() +{ + call_member value; + auto fn = std::bind_front(&call_member::member, value, 0); + assert(fn(0)); +} + +struct no_const_rvalue +{ + void operator()(int) && {}; +}; + +auto make_no_const_rvalue(int x) +{ + // This is to test that bind_front works when something like the following would not: + // return [nc = no_const_rvalue{}, x] { return nc(x); }; + // Above would not work because it would look for a () const && overload. + return std::bind_front(no_const_rvalue{}, x); +} + +void test_no_const_rvalue() +{ + make_no_const_rvalue(1)(); +} + +struct not_move_construcable +{ + not_move_construcable(not_move_construcable const&) = delete; + not_move_construcable(not_move_construcable &&) = delete; +}; + +void takes_not_move_constructable(not_move_construcable) { } + +void constructor_tests() +{ + { + MoveOnlyCallable value(true); + using RetT = decltype(std::bind_front(std::move(value), 1)); + + static_assert( std::is_move_constructible::value); + static_assert(!std::is_copy_constructible::value); + static_assert(!std::is_move_assignable::value); + static_assert(!std::is_copy_assignable::value); + + auto ret = std::bind_front(std::move(value), 1); + assert(ret()); + assert(ret(1, 2, 3)); + + auto ret1 = std::move(ret); + assert(!ret()); + assert(ret1()); + assert(ret1(1, 2, 3)); + } + { + CopyCallable value(true); + using RetT = decltype(std::bind_front(value, 1)); + + static_assert( std::is_move_constructible::value); + static_assert( std::is_copy_constructible::value); + static_assert(!std::is_move_assignable::value); + static_assert(!std::is_copy_assignable::value); + + auto ret = std::bind_front(value, 1); + assert(ret()); + assert(ret(1, 2, 3)); + + auto ret1 = std::move(ret); + assert(ret1()); + assert(ret1(1, 2, 3)); + + auto ret2 = std::bind_front(std::move(value), 1); + assert(!ret()); + assert( ret2()); + assert( ret2(1, 2, 3)); + } + { + CopyAssignableWrapper value(true); + using RetT = decltype(std::bind_front(value, 1)); + + static_assert(std::is_move_constructible::value); + static_assert(std::is_copy_constructible::value); + static_assert(std::is_move_assignable::value); + static_assert(std::is_copy_assignable::value); + } + { + MoveAssignableWrapper value(true); + using RetT = decltype(std::bind_front(std::move(value), 1)); + + static_assert( std::is_move_constructible::value); + static_assert(!std::is_copy_constructible::value); + static_assert( std::is_move_assignable::value); + static_assert(!std::is_copy_assignable::value); + } + { + static_assert(!std::is_invocable::value); + } +} + +template +void test_return(F&& value, Args&&... args) +{ + auto ret = std::bind_front(std::forward(value), std::forward(args)...); + static_assert(std::is_same::value); +} + +void test_return_types() +{ + test_return(FooCall{}, 1, 2); + test_return(S{}, 1); + test_return(add, 2, 2); +} + +void test_arg_count() +{ + using T = decltype(std::bind_front(add, 1)); + static_assert(!std::is_invocable::value); + static_assert( std::is_invocable::value); +} + +int main(int, char**) +{ + basic_tests(); + constructor_tests(); + test_return_types(); + test_arg_count(); + test_variadic(); + test_mutable(); + test_call_member(); + test_no_const_rvalue(); + + static_assert(constexpr_test()); + + return 0; +} \ No newline at end of file diff --git a/libcxx/test/std/utilities/function.objects/func.bind_front/bind_front.verify.cpp b/libcxx/test/std/utilities/function.objects/func.bind_front/bind_front.verify.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/function.objects/func.bind_front/bind_front.verify.cpp @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// functional + +// template unspecified bind_front(F&&, Args&&...); + +#include + +constexpr int pass(const int n) { return n; } + +int simple(int n) { return n; } + +template +T do_nothing(T t) { return t; } + +struct NotMoveConst +{ + NotMoveConst(NotMoveConst &&) = delete; + NotMoveConst(NotMoveConst const&) = delete; + + NotMoveConst(int) { } +}; + +void testNotMoveConst(NotMoveConst) { } + +int main(int, char**) +{ + int n = 1; + const int c = 1; + + auto p = std::bind_front(pass, c); + static_assert(p() == 1); // expected-error {{static_assert expression is not an integral constant expression}} + + auto d = std::bind_front(do_nothing, n); // expected-error {{no matching function for call to 'bind_front'}} + + auto t = std::bind_front(testNotMoveConst, NotMoveConst(0)); // expected-error {{no matching function for call to 'bind_front'}} + + return 0; +} \ No newline at end of file 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 --- 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 @@ -17,177 +17,7 @@ #include "test_macros.h" #include "type_id.h" - - -/////////////////////////////////////////////////////////////////////////////// -// CALLABLE TEST TYPES -/////////////////////////////////////////////////////////////////////////////// - -bool returns_true() { return true; } - -template -struct MoveOnlyCallable { - MoveOnlyCallable(MoveOnlyCallable const&) = delete; - MoveOnlyCallable(MoveOnlyCallable&& other) - : value(other.value) - { other.value = !other.value; } - - template - Ret operator()(Args&&...) { return Ret{value}; } - - explicit MoveOnlyCallable(bool x) : value(x) {} - Ret value; -}; - -template -struct CopyCallable { - CopyCallable(CopyCallable const& other) - : value(other.value) {} - - CopyCallable(CopyCallable&& other) - : value(other.value) { other.value = !other.value; } - - template - Ret operator()(Args&&...) { return Ret{value}; } - - explicit CopyCallable(bool x) : value(x) {} - Ret value; -}; - - -template -struct ConstCallable { - ConstCallable(ConstCallable const& other) - : value(other.value) {} - - ConstCallable(ConstCallable&& other) - : value(other.value) { other.value = !other.value; } - - template - Ret operator()(Args&&...) const { return Ret{value}; } - - explicit ConstCallable(bool x) : value(x) {} - Ret value; -}; - - - -template -struct NoExceptCallable { - NoExceptCallable(NoExceptCallable const& other) - : value(other.value) {} - - template - Ret operator()(Args&&...) noexcept { return Ret{value}; } - - template - Ret operator()(Args&&...) const noexcept { return Ret{value}; } - - explicit NoExceptCallable(bool x) : value(x) {} - Ret value; -}; - -struct CopyAssignableWrapper { - CopyAssignableWrapper(CopyAssignableWrapper const&) = default; - CopyAssignableWrapper(CopyAssignableWrapper&&) = default; - CopyAssignableWrapper& operator=(CopyAssignableWrapper const&) = default; - CopyAssignableWrapper& operator=(CopyAssignableWrapper &&) = default; - - template - bool operator()(Args&&...) { return value; } - - explicit CopyAssignableWrapper(bool x) : value(x) {} - bool value; -}; - - -struct MoveAssignableWrapper { - MoveAssignableWrapper(MoveAssignableWrapper const&) = delete; - MoveAssignableWrapper(MoveAssignableWrapper&&) = default; - MoveAssignableWrapper& operator=(MoveAssignableWrapper const&) = delete; - MoveAssignableWrapper& operator=(MoveAssignableWrapper &&) = default; - - template - bool operator()(Args&&...) { return value; } - - explicit MoveAssignableWrapper(bool x) : value(x) {} - bool value; -}; - -struct MemFunCallable { - explicit MemFunCallable(bool x) : value(x) {} - - bool return_value() const { return value; } - bool return_value_nc() { return value; } - bool value; -}; - -enum CallType : unsigned { - CT_None, - CT_NonConst = 1, - CT_Const = 2, - CT_LValue = 4, - CT_RValue = 8 -}; - -inline constexpr CallType operator|(CallType LHS, CallType RHS) { - return static_cast(static_cast(LHS) | static_cast(RHS)); -} - -struct ForwardingCallObject { - - template - bool operator()(Args&&...) & { - set_call(CT_NonConst | CT_LValue); - return true; - } - - template - bool operator()(Args&&...) const & { - set_call(CT_Const | CT_LValue); - return true; - } - - // Don't allow the call operator to be invoked as an rvalue. - template - bool operator()(Args&&...) && { - set_call(CT_NonConst | CT_RValue); - return true; - } - - template - bool operator()(Args&&...) const && { - set_call(CT_Const | CT_RValue); - return true; - } - - template - static void set_call(CallType type) { - assert(last_call_type == CT_None); - assert(last_call_args == nullptr); - last_call_type = type; - last_call_args = &makeArgumentID(); - } - - template - static bool check_call(CallType type) { - bool result = - last_call_type == type - && last_call_args - && *last_call_args == makeArgumentID(); - last_call_type = CT_None; - last_call_args = nullptr; - return result; - } - - static CallType last_call_type; - static TypeID const* last_call_args; -}; - -CallType ForwardingCallObject::last_call_type = CT_None; -TypeID const* ForwardingCallObject::last_call_args = nullptr; - - +#include "callable_types.h" /////////////////////////////////////////////////////////////////////////////// // BOOL TEST TYPES @@ -296,6 +126,10 @@ assert(ret() == false); assert(ret2() == true); assert(ret2("abc") == true); + // initialize not_fn with rvalue + auto ret3 = std::not_fn(std::move(value)); + assert(ret(0) == false); + assert(ret3(0) == true); } { using T = CopyAssignableWrapper; diff --git a/libcxx/test/support/callable_types.h b/libcxx/test/support/callable_types.h new file mode 100644 --- /dev/null +++ b/libcxx/test/support/callable_types.h @@ -0,0 +1,182 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef CALLABLE_TYPES_H +#define CALLABLE_TYPES_H + +#include "type_id.h" + +/////////////////////////////////////////////////////////////////////////////// +// CALLABLE TEST TYPES +/////////////////////////////////////////////////////////////////////////////// + +inline bool returns_true() { return true; } + +template +struct MoveOnlyCallable { + MoveOnlyCallable(MoveOnlyCallable const&) = delete; + MoveOnlyCallable(MoveOnlyCallable&& other) + : value(other.value) + { other.value = !other.value; } + + template + constexpr Ret operator()(Args&&...) { return Ret{value}; } + + explicit MoveOnlyCallable(bool x) : value(x) {} + Ret value; +}; + +template +struct CopyCallable { + CopyCallable(CopyCallable const& other) + : value(other.value) {} + + CopyCallable(CopyCallable&& other) + : value(other.value) { other.value = !other.value; } + + template + Ret operator()(Args&&...) { return Ret{value}; } + + explicit CopyCallable(bool x) : value(x) {} + Ret value; +}; + + +template +struct ConstCallable { + ConstCallable(ConstCallable const& other) + : value(other.value) {} + + ConstCallable(ConstCallable&& other) + : value(other.value) { other.value = !other.value; } + + template + Ret operator()(Args&&...) const { return Ret{value}; } + + explicit ConstCallable(bool x) : value(x) {} + Ret value; +}; + + + +template +struct NoExceptCallable { + NoExceptCallable(NoExceptCallable const& other) + : value(other.value) {} + + template + Ret operator()(Args&&...) noexcept { return Ret{value}; } + + template + Ret operator()(Args&&...) const noexcept { return Ret{value}; } + + explicit NoExceptCallable(bool x) : value(x) {} + Ret value; +}; + +struct CopyAssignableWrapper { + CopyAssignableWrapper(CopyAssignableWrapper const&) = default; + CopyAssignableWrapper(CopyAssignableWrapper&&) = default; + CopyAssignableWrapper& operator=(CopyAssignableWrapper const&) = default; + CopyAssignableWrapper& operator=(CopyAssignableWrapper &&) = default; + + template + bool operator()(Args&&...) { return value; } + + explicit CopyAssignableWrapper(bool x) : value(x) {} + bool value; +}; + + +struct MoveAssignableWrapper { + MoveAssignableWrapper(MoveAssignableWrapper const&) = delete; + MoveAssignableWrapper(MoveAssignableWrapper&&) = default; + MoveAssignableWrapper& operator=(MoveAssignableWrapper const&) = delete; + MoveAssignableWrapper& operator=(MoveAssignableWrapper &&) = default; + + template + bool operator()(Args&&...) { return value; } + + explicit MoveAssignableWrapper(bool x) : value(x) {} + bool value; +}; + +struct MemFunCallable { + explicit MemFunCallable(bool x) : value(x) {} + + bool return_value() const { return value; } + bool return_value_nc() { return value; } + bool value; +}; + +enum CallType : unsigned { + CT_None, + CT_NonConst = 1, + CT_Const = 2, + CT_LValue = 4, + CT_RValue = 8 +}; + +inline constexpr CallType operator|(CallType LHS, CallType RHS) { + return static_cast(static_cast(LHS) | static_cast(RHS)); +} + +struct ForwardingCallObject { + + template + bool operator()(Args&&...) & { + set_call(CT_NonConst | CT_LValue); + return true; + } + + template + bool operator()(Args&&...) const & { + set_call(CT_Const | CT_LValue); + return true; + } + + // Don't allow the call operator to be invoked as an rvalue. + template + bool operator()(Args&&...) && { + set_call(CT_NonConst | CT_RValue); + return true; + } + + template + bool operator()(Args&&...) const && { + set_call(CT_Const | CT_RValue); + return true; + } + + template + static void set_call(CallType type) { + assert(last_call_type == CT_None); + assert(last_call_args == nullptr); + last_call_type = type; + last_call_args = &makeArgumentID(); + } + + template + static bool check_call(CallType type) { + bool result = + last_call_type == type + && last_call_args + && *last_call_args == makeArgumentID(); + last_call_type = CT_None; + last_call_args = nullptr; + return result; + } + + static CallType last_call_type; + static TypeID const* last_call_args; +}; + +CallType ForwardingCallObject::last_call_type = CT_None; +TypeID const* ForwardingCallObject::last_call_args = nullptr; + +#endif // CALLABLE_TYPES_H \ No newline at end of file diff --git a/libcxx/www/cxx2a_status.html b/libcxx/www/cxx2a_status.html --- a/libcxx/www/cxx2a_status.html +++ b/libcxx/www/cxx2a_status.html @@ -108,7 +108,7 @@ P0318R1LWGunwrap_ref_decay and unwrap_referenceSan DiegoComplete8.0 - P0356R5LWGSimplified partial function applicationSan Diego + P0356R5LWGSimplified partial function applicationSan DiegoComplete P0357R3LWGreference_wrapper for incomplete typesSan DiegoComplete8.0 P0482R6CWGchar8_t: A type for UTF-8 characters and stringsSan Diego P0487R1LWGFixing operator>>(basic_istream&, CharT*) (LWG 2499)San DiegoComplete8.0 @@ -187,7 +187,7 @@ P1643LWGAdd wait/notify to atomic_refCologne P1644LWGAdd wait/notify to atomicCologne P1650LWGOutput std::chrono::days with 'd' suffixCologne - P1651LWGbind_front should not unwrap reference_wrapperCologne + P1651LWGbind_front should not unwrap reference_wrapperCologneComplete P1652LWGPrintf corner cases in std::formatCologne P1661LWGRemove dedicated precalculated hash lookup interfaceCologneNothing to do P1754LWGRename concepts to standard_case for C++20, while we still canCologne @@ -424,7 +424,7 @@ 3158tuple(allocator_arg_t, const Alloc&) should be conditionally explicitCologne 3169ranges permutation generators discard useful informationCologne 3183Normative permission to specialize Ranges variable templatesCologne - 3184Inconsistencies in bind_front wordingCologne + 3184Inconsistencies in bind_front wordingCologneComplete 3185Uses-allocator construction functions missing constexpr and noexceptCologne 3186ranges removal, partition, and partial_sort_copy algorithms discard useful informationCologne 3187P0591R4 reverted DR 2586 fixes to scoped_allocator_adaptor::construct()Cologne