Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions libcxx/docs/FeatureTestMacroTable.rst
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,8 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_mdspan`` ``202406L``
---------------------------------------------------------- -----------------
``__cpp_lib_not_fn`` ``202306L``
---------------------------------------------------------- -----------------
``__cpp_lib_optional_range_support`` *unimplemented*
---------------------------------------------------------- -----------------
``__cpp_lib_out_ptr`` ``202311L``
Expand Down
2 changes: 1 addition & 1 deletion libcxx/docs/Status/Cxx2cPapers.csv
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"`P1383R2 <https://wg21.link/P1383R2>`__","More ``constexpr`` for ``<cmath>`` and ``<complex>``","2023-06 (Varna)","","",""
"`P2734R0 <https://wg21.link/P2734R0>`__","Adding the new SI prefixes","2023-06 (Varna)","|Complete|","17",""
"`P2548R6 <https://wg21.link/P2548R6>`__","``copyable_function``","2023-06 (Varna)","","",""
"`P2714R1 <https://wg21.link/P2714R1>`__","Bind front and back to NTTP callables","2023-06 (Varna)","","",""
"`P2714R1 <https://wg21.link/P2714R1>`__","Bind front and back to NTTP callables","2023-06 (Varna)","|Partial|","20","``not_fn`` only"
"`P2630R4 <https://wg21.link/P2630R4>`__","``submdspan``","2023-06 (Varna)","","",""
"","","","","",""
"`P0543R3 <https://wg21.link/P0543R3>`__","Saturation arithmetic","2023-11 (Kona)","|Complete|","18",""
Expand Down
23 changes: 23 additions & 0 deletions libcxx/include/__functional/not_fn.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
#include <__type_traits/decay.h>
#include <__type_traits/enable_if.h>
#include <__type_traits/is_constructible.h>
#include <__type_traits/is_member_pointer.h>
#include <__type_traits/is_pointer.h>
#include <__utility/forward.h>

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

#endif // _LIBCPP_STD_VER >= 17

#if _LIBCPP_STD_VER >= 26

template <auto _Fn>
struct __nttp_not_fn_t {
template <class... _Args>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Args&&... __args) const
noexcept(noexcept(!std::invoke(_Fn, std::forward<_Args>(__args)...)))
-> decltype(!std::invoke(_Fn, std::forward<_Args>(__args)...)) {
return !std::invoke(_Fn, std::forward<_Args>(__args)...);
}
};

template <auto _Fn>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI constexpr auto not_fn() noexcept {
if constexpr (using _Ty = decltype(_Fn); is_pointer_v<_Ty> || is_member_pointer_v<_Ty>)
static_assert(_Fn != nullptr, "f cannot be equal to nullptr");
return __nttp_not_fn_t<_Fn>();
}

#endif // _LIBCPP_STD_VER >= 26

_LIBCPP_END_NAMESPACE_STD

#endif // _LIBCPP___FUNCTIONAL_NOT_FN_H
4 changes: 3 additions & 1 deletion libcxx/include/functional
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,9 @@ template <class Predicate> // deprecated in C++17, removed in C++20
binary_negate<Predicate> not2(const Predicate& pred);

template <class F>
constexpr unspecified not_fn(F&& f); // C++17, constexpr in C++20
constexpr unspecified not_fn(F&& f); // C++17, constexpr in C++20
template <auto f>
constexpr unspecified not_fn() noexcept; // C++26

// [func.bind.partial], function templates bind_front and bind_back
template<class F, class... Args>
Expand Down
5 changes: 4 additions & 1 deletion libcxx/include/version
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,8 @@ __cpp_lib_nonmember_container_access 201411L <array> <deque>
<iterator> <list> <map>
<regex> <set> <string>
<unordered_map> <unordered_set> <vector>
__cpp_lib_not_fn 201603L <functional>
__cpp_lib_not_fn 202306L <functional>
201603L // C++17
__cpp_lib_null_iterators 201304L <iterator>
__cpp_lib_optional 202110L <optional>
202106L // C++20
Expand Down Expand Up @@ -557,6 +558,8 @@ __cpp_lib_void_t 201411L <type_traits>
// # define __cpp_lib_linalg 202311L
# undef __cpp_lib_mdspan
# define __cpp_lib_mdspan 202406L
# undef __cpp_lib_not_fn
# define __cpp_lib_not_fn 202306L
// # define __cpp_lib_optional_range_support 202406L
# undef __cpp_lib_out_ptr
# define __cpp_lib_out_ptr 202311L
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//===----------------------------------------------------------------------===//
//
// 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++03, c++11, c++14, c++17, c++20, c++23

// <functional>

// Type of `std::not_fn<NTTP>()` is always empty.

#include <functional>
#include <type_traits>

struct NonEmptyFunctionObject {
bool val = true;
bool operator()() const;
};

bool func();

struct SomeClass {
bool member_object;
bool member_function();
};

using ResultWithEmptyFuncObject = decltype(std::not_fn<std::false_type{}>());
static_assert(std::is_empty_v<ResultWithEmptyFuncObject>);

using ResultWithNotEmptyFuncObject = decltype(std::not_fn<NonEmptyFunctionObject{}>());
static_assert(std::is_empty_v<ResultWithNotEmptyFuncObject>);

using ResultWithFunctionPointer = decltype(std::not_fn<&func>());
static_assert(std::is_empty_v<ResultWithFunctionPointer>);

using ResultWithMemberObjectPointer = decltype(std::not_fn<&SomeClass::member_object>());
static_assert(std::is_empty_v<ResultWithMemberObjectPointer>);

using ResultWithMemberFunctionPointer = decltype(std::not_fn<&SomeClass::member_function>());
static_assert(std::is_empty_v<ResultWithMemberFunctionPointer>);
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//===----------------------------------------------------------------------===//
//
// 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++03, c++11, c++14, c++17, c++20, c++23

// <functional>

// Test the libc++ extension that std::not_fn<NTTP> is marked as [[nodiscard]].

#include <functional>
#include <type_traits>

void test() {
using F = std::true_type;
std::not_fn<F{}>(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}

auto negated = std::not_fn<F{}>();
negated(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
__cpp_lib_invoke_r 202106L [C++23]
__cpp_lib_move_only_function 202110L [C++23]
__cpp_lib_not_fn 201603L [C++17]
202306L [C++26]
__cpp_lib_ranges 202110L [C++20]
202406L [C++23]
__cpp_lib_reference_wrapper 202403L [C++26]
Expand Down Expand Up @@ -525,8 +526,8 @@
# ifndef __cpp_lib_not_fn
# error "__cpp_lib_not_fn should be defined in c++26"
# endif
# if __cpp_lib_not_fn != 201603L
# error "__cpp_lib_not_fn should have the value 201603L in c++26"
# if __cpp_lib_not_fn != 202306L
# error "__cpp_lib_not_fn should have the value 202306L in c++26"
# endif

# ifndef __cpp_lib_ranges
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@
__cpp_lib_node_extract 201606L [C++17]
__cpp_lib_nonmember_container_access 201411L [C++17]
__cpp_lib_not_fn 201603L [C++17]
202306L [C++26]
__cpp_lib_null_iterators 201304L [C++14]
__cpp_lib_optional 201606L [C++17]
202106L [C++20]
Expand Down Expand Up @@ -7405,8 +7406,8 @@
# ifndef __cpp_lib_not_fn
# error "__cpp_lib_not_fn should be defined in c++26"
# endif
# if __cpp_lib_not_fn != 201603L
# error "__cpp_lib_not_fn should have the value 201603L in c++26"
# if __cpp_lib_not_fn != 202306L
# error "__cpp_lib_not_fn should have the value 202306L in c++26"
# endif

# ifndef __cpp_lib_null_iterators
Expand Down
Loading
Loading