Index: libcxx/www/cxx2a_status.html
===================================================================
--- libcxx/www/cxx2a_status.html
+++ libcxx/www/cxx2a_status.html
@@ -108,7 +108,7 @@
| | | | | |
P0318R1 | LWG | unwrap_ref_decay and unwrap_reference | San Diego | Complete | 8.0 |
- P0356R5 | LWG | Simplified partial function application | San Diego | | |
+ P0356R5 | LWG | Simplified partial function application | San Diego | Complete | |
P0357R3 | LWG | reference_wrapper for incomplete types | San Diego | Complete | 8.0 |
P0482R6 | CWG | char8_t: A type for UTF-8 characters and strings | San Diego | | |
P0487R1 | LWG | Fixing operator>>(basic_istream&, CharT*) (LWG 2499) | San Diego | Complete | 8.0 |
@@ -187,7 +187,7 @@
P1643 | LWG | Add wait/notify to atomic_ref | Cologne | | |
P1644 | LWG | Add wait/notify to atomic | Cologne | | |
P1650 | LWG | Output std::chrono::days with 'd' suffix | Cologne | | |
- P1651 | LWG | bind_front should not unwrap reference_wrapper | Cologne | | |
+ P1651 | LWG | bind_front should not unwrap reference_wrapper | Cologne | Complete | |
P1652 | LWG | Printf corner cases in std::format | Cologne | | |
P1661 | LWG | Remove dedicated precalculated hash lookup interface | Cologne | | |
P1754 | LWG | Rename concepts to standard_case for C++20, while we still can | Cologne | | |
@@ -363,7 +363,7 @@
3158 | tuple(allocator_arg_t, const Alloc&) should be conditionally explicit | Cologne | |
3169 | ranges permutation generators discard useful information | Cologne | |
3183 | Normative permission to specialize Ranges variable templates | Cologne | |
- 3184 | Inconsistencies in bind_front wording | Cologne | |
+ 3184 | Inconsistencies in bind_front wording | Cologne | Complete |
3185 | Uses-allocator construction functions missing constexpr and noexcept | Cologne | |
3186 | ranges removal, partition, and partial_sort_copy algorithms discard useful information | Cologne | |
3187 | P0591R4 reverted DR 2586 fixes to scoped_allocator_adaptor::construct() | Cologne | |
Index: libcxx/test/support/callable_types.h
===================================================================
--- /dev/null
+++ 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
Index: libcxx/test/std/utilities/function.objects/func.not_fn/not_fn.pass.cpp
===================================================================
--- libcxx/test/std/utilities/function.objects/func.not_fn/not_fn.pass.cpp
+++ 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;
Index: libcxx/test/std/utilities/function.objects/func.bind_front/bind_front.pass.cpp
===================================================================
--- /dev/null
+++ libcxx/test/std/utilities/function.objects/func.bind_front/bind_front.pass.cpp
@@ -0,0 +1,225 @@
+//===----------------------------------------------------------------------===//
+//
+// 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)();
+}
+
+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);
+ }
+}
+
+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
Index: libcxx/test/std/utilities/function.objects/func.bind_front/bind_front.fail.cpp
===================================================================
--- /dev/null
+++ libcxx/test/std/utilities/function.objects/func.bind_front/bind_front.fail.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-re@functional:* {{no matching constructor for initialization of {{.+}}}}
+
+ return 0;
+}
\ No newline at end of file
Index: libcxx/include/functional
===================================================================
--- libcxx/include/functional
+++ libcxx/include/functional
@@ -2902,61 +2902,114 @@
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 struct __bool_pack;
+template
+using __all_true = _VSTD::is_same<__bool_pack<_BArgs..., true>, __bool_pack>;
+
+template::value>::type>
+struct __perfect_forward_impl;
+
+template
+struct __perfect_forward_impl<_Op, __tuple_types<_Bound...>, __tuple_indices<_Idxs...>>
+{
+ _VSTD::tuple<_Bound...> __bound;
+
+ template
+ 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
+ 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
+ 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
+ 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, _BoundArgs...>::value &&
+ __all_true::value...>::value>>
+ 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_v>>>
+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
@@ -3082,13 +3135,13 @@
template
inline void __libcpp_erase_if_container( _Container& __c, _Predicate __pred)
{
- for (typename _Container::iterator __iter = __c.begin(), __last = __c.end(); __iter != __last;)
- {
- if (__pred(*__iter))
- __iter = __c.erase(__iter);
- else
- ++__iter;
- }
+ for (typename _Container::iterator __iter = __c.begin(), __last = __c.end(); __iter != __last;)
+ {
+ if (__pred(*__iter))
+ __iter = __c.erase(__iter);
+ else
+ ++__iter;
+ }
}
_LIBCPP_END_NAMESPACE_STD