Skip to content

Commit fc15d9f

Browse files
committed
[libc++] Implement not_fn<NTTP>
Implement `not_fn<NTTP>` function from "P2714R1 Bind front and back to NTTP callables".
1 parent 8070b2d commit fc15d9f

File tree

13 files changed

+415
-9
lines changed

13 files changed

+415
-9
lines changed

libcxx/docs/FeatureTestMacroTable.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,8 @@ Status
438438
---------------------------------------------------------- -----------------
439439
``__cpp_lib_linalg`` *unimplemented*
440440
---------------------------------------------------------- -----------------
441+
``__cpp_lib_not_fn`` ``202306L``
442+
---------------------------------------------------------- -----------------
441443
``__cpp_lib_out_ptr`` *unimplemented*
442444
---------------------------------------------------------- -----------------
443445
``__cpp_lib_ranges_concat`` *unimplemented*

libcxx/docs/Status/Cxx2c.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ Paper Status
4040
.. note::
4141

4242
.. [#note-P2510R3] This paper is applied as DR against C++20. (MSVC STL and libstdc++ will do the same.)
43+
.. [#note-P2714R1] ``not_fn`` is done.
4344
.. [#note-P3142R0] This paper is applied as DR against C++23. (MSVC STL and libstdc++ will do the same.)
4445
.. [#note-P2944R3] Implemented comparisons for ``reference_wrapper`` only.
4546

libcxx/docs/Status/Cxx2cPapers.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
"`P1383R2 <https://wg21.link/P1383R2>`__","LWG","More ``constexpr`` for ``<cmath>`` and ``<complex>``","Varna June 2023","","",""
2525
"`P2734R0 <https://wg21.link/P2734R0>`__","LWG","Adding the new SI prefixes","Varna June 2023","|Complete|","17.0",""
2626
"`P2548R6 <https://wg21.link/P2548R6>`__","LWG","``copyable_function``","Varna June 2023","","",""
27-
"`P2714R1 <https://wg21.link/P2714R1>`__","LWG","Bind front and back to NTTP callables","Varna June 2023","","",""
27+
"`P2714R1 <https://wg21.link/P2714R1>`__","LWG","Bind front and back to NTTP callables","Varna June 2023","|Partial| [#note-P2714R1]_","19.0",""
2828
"`P2630R4 <https://wg21.link/P2630R4>`__","LWG","``submdspan``","Varna June 2023","","",""
2929
"","","","","","",""
3030
"`P0543R3 <https://wg21.link/P0543R3>`__","LWG","Saturation arithmetic","Kona November 2023","|Complete|","18.0",""

libcxx/include/__functional/not_fn.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
#include <__type_traits/decay.h>
1717
#include <__type_traits/enable_if.h>
1818
#include <__type_traits/is_constructible.h>
19+
#include <__type_traits/is_member_pointer.h>
20+
#include <__type_traits/is_pointer.h>
1921
#include <__utility/forward.h>
2022

2123
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -48,6 +50,27 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 auto not_fn(_Fn&& __f) {
4850

4951
#endif // _LIBCPP_STD_VER >= 17
5052

53+
#if _LIBCPP_STD_VER >= 26
54+
55+
template <auto _Fn>
56+
struct __nttp_not_fn_t {
57+
template <class... _Args>
58+
_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Args&&... __args) const
59+
noexcept(noexcept(!std::invoke(_Fn, std::forward<_Args>(__args)...)))
60+
-> decltype(!std::invoke(_Fn, std::forward<_Args>(__args)...)) {
61+
return !std::invoke(_Fn, std::forward<_Args>(__args)...);
62+
}
63+
};
64+
65+
template <auto _Fn>
66+
_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI constexpr auto not_fn() noexcept {
67+
if constexpr (using _Ty = decltype(_Fn); is_pointer_v<_Ty> || is_member_pointer_v<_Ty>)
68+
static_assert(_Fn != nullptr, "f cannot be equal to nullptr");
69+
return __nttp_not_fn_t<_Fn>();
70+
}
71+
72+
#endif // _LIBCPP_STD_VER >= 26
73+
5174
_LIBCPP_END_NAMESPACE_STD
5275

5376
#endif // _LIBCPP___FUNCTIONAL_NOT_FN_H

libcxx/include/functional

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,9 @@ template <class Predicate> // deprecated in C++17, removed in C++20
214214
binary_negate<Predicate> not2(const Predicate& pred);
215215
216216
template <class F>
217-
constexpr unspecified not_fn(F&& f); // C++17, constexpr in C++20
217+
constexpr unspecified not_fn(F&& f); // C++17, constexpr in C++20
218+
template <auto f>
219+
constexpr unspecified not_fn() noexcept; // C++26
218220
219221
// [func.bind.partial], function templates bind_front and bind_back
220222
template<class F, class... Args>

libcxx/include/version

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,8 @@ __cpp_lib_nonmember_container_access 201411L <array> <deque>
165165
<iterator> <list> <map>
166166
<regex> <set> <string>
167167
<unordered_map> <unordered_set> <vector>
168-
__cpp_lib_not_fn 201603L <functional>
168+
__cpp_lib_not_fn 202306L <functional>
169+
201603L // C++17
169170
__cpp_lib_null_iterators 201304L <iterator>
170171
__cpp_lib_optional 202110L <optional>
171172
201606L // C++17
@@ -521,6 +522,8 @@ __cpp_lib_within_lifetime 202306L <type_traits>
521522
// # define __cpp_lib_generate_random 202403L
522523
// # define __cpp_lib_hazard_pointer 202306L
523524
// # define __cpp_lib_linalg 202311L
525+
# undef __cpp_lib_not_fn
526+
# define __cpp_lib_not_fn 202306L
524527
# undef __cpp_lib_out_ptr
525528
// # define __cpp_lib_out_ptr 202311L
526529
// # define __cpp_lib_ranges_concat 202403L
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
10+
11+
// <functional>
12+
13+
// Test implementation-defined properties of std::not_fn<NTTP>.
14+
15+
#include <functional>
16+
#include <type_traits>
17+
18+
struct NotEmptyFunctionObject {
19+
bool val = true;
20+
bool operator()() const; // not defined
21+
};
22+
23+
void test() {
24+
using ResultWithEmptyFuncObject = decltype(std::not_fn<std::false_type{}>());
25+
static_assert(std::is_empty_v<ResultWithEmptyFuncObject>);
26+
27+
using ResultWithNotEmptyFuncObject = decltype(std::not_fn<NotEmptyFunctionObject{}>());
28+
static_assert(std::is_empty_v<ResultWithNotEmptyFuncObject>);
29+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
10+
11+
// <functional>
12+
13+
// Test the libc++ extension that std::not_fn<NTTP> is marked as [[nodiscard]].
14+
15+
#include <functional>
16+
#include <type_traits>
17+
18+
void test() {
19+
using F = std::true_type;
20+
std::not_fn<F{}>(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
21+
}

libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.compile.pass.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
__cpp_lib_invoke_r 202106L [C++23]
2828
__cpp_lib_move_only_function 202110L [C++23]
2929
__cpp_lib_not_fn 201603L [C++17]
30+
202306L [C++26]
3031
__cpp_lib_ranges 202207L [C++20]
3132
__cpp_lib_reference_wrapper 202403L [C++26]
3233
__cpp_lib_result_of_sfinae 201210L [C++14]
@@ -524,8 +525,8 @@
524525
# ifndef __cpp_lib_not_fn
525526
# error "__cpp_lib_not_fn should be defined in c++26"
526527
# endif
527-
# if __cpp_lib_not_fn != 201603L
528-
# error "__cpp_lib_not_fn should have the value 201603L in c++26"
528+
# if __cpp_lib_not_fn != 202306L
529+
# error "__cpp_lib_not_fn should have the value 202306L in c++26"
529530
# endif
530531

531532
# ifndef __cpp_lib_ranges

libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@
149149
__cpp_lib_node_extract 201606L [C++17]
150150
__cpp_lib_nonmember_container_access 201411L [C++17]
151151
__cpp_lib_not_fn 201603L [C++17]
152+
202306L [C++26]
152153
__cpp_lib_null_iterators 201304L [C++14]
153154
__cpp_lib_optional 201606L [C++17]
154155
202110L [C++23]
@@ -7207,8 +7208,8 @@
72077208
# ifndef __cpp_lib_not_fn
72087209
# error "__cpp_lib_not_fn should be defined in c++26"
72097210
# endif
7210-
# if __cpp_lib_not_fn != 201603L
7211-
# error "__cpp_lib_not_fn should have the value 201603L in c++26"
7211+
# if __cpp_lib_not_fn != 202306L
7212+
# error "__cpp_lib_not_fn should have the value 202306L in c++26"
72127213
# endif
72137214

72147215
# ifndef __cpp_lib_null_iterators

0 commit comments

Comments
 (0)