[libcxx-commits] [libcxx] e06f1a8 - [libcxx] reworks invocable and regular_invocable tests
Christopher Di Bella via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Mar 29 08:37:47 PDT 2021
Author: Christopher Di Bella
Date: 2021-03-29T15:26:05Z
New Revision: e06f1a8e3cc60bb8d2a937f47f6dac06a8818a17
URL: https://github.com/llvm/llvm-project/commit/e06f1a8e3cc60bb8d2a937f47f6dac06a8818a17
DIFF: https://github.com/llvm/llvm-project/commit/e06f1a8e3cc60bb8d2a937f47f6dac06a8818a17.diff
LOG: [libcxx] reworks invocable and regular_invocable tests
The tests for `std::invocable` and `std::regular_invocable` were
woefully incomplete. This patch closes many of the gaps (though some
probably remain).
Differential Revision: https://reviews.llvm.org/D99398
Added:
Modified:
libcxx/test/std/concepts/concepts.callable/concept.invocable/invocable.compile.pass.cpp
libcxx/test/std/concepts/concepts.callable/concept.regularinvocable/regular_invocable.pass.cpp
Removed:
libcxx/test/std/concepts/concepts.callable/functions.h
################################################################################
diff --git a/libcxx/test/std/concepts/concepts.callable/concept.invocable/invocable.compile.pass.cpp b/libcxx/test/std/concepts/concepts.callable/concept.invocable/invocable.compile.pass.cpp
index f201910d5031..7789c02d199e 100644
--- a/libcxx/test/std/concepts/concepts.callable/concept.invocable/invocable.compile.pass.cpp
+++ b/libcxx/test/std/concepts/concepts.callable/concept.invocable/invocable.compile.pass.cpp
@@ -18,17 +18,41 @@
#include <random>
#include <type_traits>
-#include "../functions.h"
+template <class R, class... Args>
+[[nodiscard]] constexpr bool check_invocable() {
+ constexpr bool result = std::invocable<R(Args...), Args...>;
+ static_assert(std::invocable<R(Args...) noexcept, Args...> == result);
+ static_assert(std::invocable<R (*)(Args...), Args...> == result);
+ static_assert(std::invocable<R (*)(Args...) noexcept, Args...> == result);
+ static_assert(std::invocable<R (&)(Args...), Args...> == result);
+ static_assert(std::invocable<R (&)(Args...) noexcept, Args...> == result);
-// clang-format off
-template <class F, class... Args>
-requires std::invocable<F, Args...>
-constexpr void ModelsInvocable(F, Args&&...) noexcept{}
+ return result;
+}
-template <class F, class... Args>
-requires(!std::invocable<F, Args...>)
-constexpr void NotInvocable(F, Args&&...) noexcept {}
-// clang-format on
+static_assert(check_invocable<void>());
+static_assert(check_invocable<void, int>());
+static_assert(check_invocable<void, int&>());
+static_assert(check_invocable<void, int*, double>());
+static_assert(check_invocable<int>());
+static_assert(check_invocable<int, int[]>());
+
+struct S;
+static_assert(check_invocable<int, int S::*, std::nullptr_t>());
+static_assert(check_invocable<int, int (S::*)(), int (S::*)(int), int>());
+static_assert(std::invocable<void (*)(int const&), int&>);
+static_assert(std::invocable<void (*)(int const&), int&&>);
+static_assert(std::invocable<void (*)(int volatile&), int&>);
+static_assert(std::invocable<void (*)(int const volatile&), int&>);
+
+static_assert(!std::invocable<void(), int>);
+static_assert(!std::invocable<void(int)>);
+static_assert(!std::invocable<void(int*), double*>);
+static_assert(!std::invocable<void (*)(int&), double*>);
+static_assert(std::invocable<int S::*, std::unique_ptr<S> >);
+static_assert(std::invocable<int S::*, std::shared_ptr<S> >);
+static_assert(!std::invocable<void (*)(int&&), int&>);
+static_assert(!std::invocable<void (*)(int&&), int const&>);
static_assert(!std::invocable<void>);
static_assert(!std::invocable<void*>);
@@ -36,84 +60,372 @@ static_assert(!std::invocable<int>);
static_assert(!std::invocable<int&>);
static_assert(!std::invocable<int&&>);
-int main(int, char**) {
- {
- using namespace RegularInvocable;
-
- ModelsInvocable(F);
- NotInvocable(F, 0);
-
- ModelsInvocable(G, 2);
- NotInvocable(G);
- NotInvocable(G, 3, 0);
-
- NotInvocable(&A::I);
- NotInvocable(&A::F);
-
- {
- A X;
- ModelsInvocable(&A::I, X);
- ModelsInvocable(&A::F, X);
- ModelsInvocable(&A::G, X, 0);
- NotInvocable(&A::G, X);
- NotInvocable(&A::G, 0);
- NotInvocable(&A::H);
-
- A const& Y = X;
- ModelsInvocable(&A::I, Y);
- ModelsInvocable(&A::F, Y);
- NotInvocable(&A::G, Y, 0);
- NotInvocable(&A::H, Y, 0);
- }
-
- ModelsInvocable(&A::I, A{});
- ModelsInvocable(&A::F, A{});
- ModelsInvocable(&A::G, A{}, 0);
- ModelsInvocable(&A::H, A{}, 0);
-
- {
- auto Up = std::make_unique<A>();
- ModelsInvocable(&A::I, Up);
- ModelsInvocable(&A::F, Up);
- ModelsInvocable(&A::G, Up, 0);
- NotInvocable(&A::H, Up, 0);
- }
- {
- auto Sp = std::make_shared<A>();
- ModelsInvocable(&A::I, Sp);
- ModelsInvocable(&A::F, Sp);
- ModelsInvocable(&A::G, Sp, 0);
- NotInvocable(&A::H, Sp, 0);
- }
- }
- {
- using namespace Predicate;
- {
- ModelsInvocable(L2rSorted{}, 0, 1, 2);
- NotInvocable(L2rSorted{});
- NotInvocable(L2rSorted{}, 0);
- NotInvocable(L2rSorted{}, 0, 1);
- }
- {
- auto Up = std::make_unique<L2rSorted>();
- ModelsInvocable(&L2rSorted::operator()<int>, Up, 0, 1, 2);
- NotInvocable(&L2rSorted::operator()<int>, Up);
- NotInvocable(&L2rSorted::operator()<int>, Up, 0);
- NotInvocable(&L2rSorted::operator()<int>, Up, 0, 1);
- }
- {
- auto Sp = std::make_shared<L2rSorted>();
- ModelsInvocable(&L2rSorted::operator()<int>, Sp, 0, 1, 2);
- NotInvocable(&L2rSorted::operator()<int>, Sp);
- NotInvocable(&L2rSorted::operator()<int>, Sp, 0);
- NotInvocable(&L2rSorted::operator()<int>, Sp, 0, 1);
- }
- }
+namespace function_objects {
+struct function_object {
+ void operator()();
+};
+static_assert(std::invocable<function_object>);
+static_assert(!std::invocable<function_object const>);
+static_assert(!std::invocable<function_object volatile>);
+static_assert(!std::invocable<function_object const volatile>);
+static_assert(std::invocable<function_object&>);
+static_assert(!std::invocable<function_object const&>);
+static_assert(!std::invocable<function_object volatile&>);
+static_assert(!std::invocable<function_object const volatile&>);
+
+struct const_function_object {
+ void operator()(int) const;
+};
+static_assert(std::invocable<const_function_object, int>);
+static_assert(std::invocable<const_function_object const, int>);
+static_assert(!std::invocable<const_function_object volatile, int>);
+static_assert(!std::invocable<const_function_object const volatile, int>);
+static_assert(std::invocable<const_function_object&, int>);
+static_assert(std::invocable<const_function_object const&, int>);
+static_assert(!std::invocable<const_function_object volatile&, int>);
+static_assert(!std::invocable<const_function_object const volatile&, int>);
+
+struct volatile_function_object {
+ void operator()(int, int) volatile;
+};
+static_assert(std::invocable<volatile_function_object, int, int>);
+static_assert(!std::invocable<volatile_function_object const, int, int>);
+static_assert(std::invocable<volatile_function_object volatile, int, int>);
+static_assert(
+ !std::invocable<volatile_function_object const volatile, int, int>);
+static_assert(std::invocable<volatile_function_object&, int, int>);
+static_assert(!std::invocable<volatile_function_object const&, int, int>);
+static_assert(std::invocable<volatile_function_object volatile&, int, int>);
+static_assert(
+ !std::invocable<volatile_function_object const volatile&, int, int>);
+
+struct cv_function_object {
+ void operator()(int[]) const volatile;
+};
+static_assert(std::invocable<cv_function_object, int*>);
+static_assert(std::invocable<cv_function_object const, int*>);
+static_assert(std::invocable<cv_function_object volatile, int*>);
+static_assert(std::invocable<cv_function_object const volatile, int*>);
+static_assert(std::invocable<cv_function_object&, int*>);
+static_assert(std::invocable<cv_function_object const&, int*>);
+static_assert(std::invocable<cv_function_object volatile&, int*>);
+static_assert(std::invocable<cv_function_object const volatile&, int*>);
+
+struct lvalue_function_object {
+ void operator()() &;
+};
+static_assert(!std::invocable<lvalue_function_object>);
+static_assert(!std::invocable<lvalue_function_object const>);
+static_assert(!std::invocable<lvalue_function_object volatile>);
+static_assert(!std::invocable<lvalue_function_object const volatile>);
+static_assert(std::invocable<lvalue_function_object&>);
+static_assert(!std::invocable<lvalue_function_object const&>);
+static_assert(!std::invocable<lvalue_function_object volatile&>);
+static_assert(!std::invocable<lvalue_function_object const volatile&>);
+
+struct lvalue_const_function_object {
+ void operator()(int) const&;
+};
+static_assert(std::invocable<lvalue_const_function_object, int>);
+static_assert(std::invocable<lvalue_const_function_object const, int>);
+static_assert(!std::invocable<lvalue_const_function_object volatile, int>);
+static_assert(
+ !std::invocable<lvalue_const_function_object const volatile, int>);
+static_assert(std::invocable<lvalue_const_function_object&, int>);
+static_assert(std::invocable<lvalue_const_function_object const&, int>);
+static_assert(!std::invocable<lvalue_const_function_object volatile&, int>);
+static_assert(
+ !std::invocable<lvalue_const_function_object const volatile&, int>);
+
+struct lvalue_volatile_function_object {
+ void operator()(int, int) volatile&;
+};
+static_assert(!std::invocable<lvalue_volatile_function_object, int, int>);
+static_assert(!std::invocable<lvalue_volatile_function_object const, int, int>);
+static_assert(
+ !std::invocable<lvalue_volatile_function_object volatile, int, int>);
+static_assert(
+ !std::invocable<lvalue_volatile_function_object const volatile, int, int>);
+static_assert(std::invocable<lvalue_volatile_function_object&, int, int>);
+static_assert(
+ !std::invocable<lvalue_volatile_function_object const&, int, int>);
+static_assert(
+ std::invocable<lvalue_volatile_function_object volatile&, int, int>);
+static_assert(
+ !std::invocable<lvalue_volatile_function_object const volatile&, int, int>);
+
+struct lvalue_cv_function_object {
+ void operator()(int[]) const volatile&;
+};
+static_assert(!std::invocable<lvalue_cv_function_object, int*>);
+static_assert(!std::invocable<lvalue_cv_function_object const, int*>);
+static_assert(!std::invocable<lvalue_cv_function_object volatile, int*>);
+static_assert(!std::invocable<lvalue_cv_function_object const volatile, int*>);
+static_assert(std::invocable<lvalue_cv_function_object&, int*>);
+static_assert(std::invocable<lvalue_cv_function_object const&, int*>);
+static_assert(std::invocable<lvalue_cv_function_object volatile&, int*>);
+static_assert(std::invocable<lvalue_cv_function_object const volatile&, int*>);
+//
+struct rvalue_function_object {
+ void operator()() &&;
+};
+static_assert(std::invocable<rvalue_function_object>);
+static_assert(!std::invocable<rvalue_function_object const>);
+static_assert(!std::invocable<rvalue_function_object volatile>);
+static_assert(!std::invocable<rvalue_function_object const volatile>);
+static_assert(!std::invocable<rvalue_function_object&>);
+static_assert(!std::invocable<rvalue_function_object const&>);
+static_assert(!std::invocable<rvalue_function_object volatile&>);
+static_assert(!std::invocable<rvalue_function_object const volatile&>);
+
+struct rvalue_const_function_object {
+ void operator()(int) const&&;
+};
+static_assert(std::invocable<rvalue_const_function_object, int>);
+static_assert(std::invocable<rvalue_const_function_object const, int>);
+static_assert(!std::invocable<rvalue_const_function_object volatile, int>);
+static_assert(
+ !std::invocable<rvalue_const_function_object const volatile, int>);
+static_assert(!std::invocable<rvalue_const_function_object&, int>);
+static_assert(!std::invocable<rvalue_const_function_object const&, int>);
+static_assert(!std::invocable<rvalue_const_function_object volatile&, int>);
+static_assert(
+ !std::invocable<rvalue_const_function_object const volatile&, int>);
+
+struct rvalue_volatile_function_object {
+ void operator()(int, int) volatile&&;
+};
+static_assert(std::invocable<rvalue_volatile_function_object, int, int>);
+static_assert(!std::invocable<rvalue_volatile_function_object const, int, int>);
+static_assert(
+ std::invocable<rvalue_volatile_function_object volatile, int, int>);
+static_assert(
+ !std::invocable<rvalue_volatile_function_object const volatile, int, int>);
+static_assert(!std::invocable<rvalue_volatile_function_object&, int, int>);
+static_assert(
+ !std::invocable<rvalue_volatile_function_object const&, int, int>);
+static_assert(
+ !std::invocable<rvalue_volatile_function_object volatile&, int, int>);
+static_assert(
+ !std::invocable<rvalue_volatile_function_object const volatile&, int, int>);
+
+struct rvalue_cv_function_object {
+ void operator()(int[]) const volatile&&;
+};
+static_assert(std::invocable<rvalue_cv_function_object, int*>);
+static_assert(std::invocable<rvalue_cv_function_object const, int*>);
+static_assert(std::invocable<rvalue_cv_function_object volatile, int*>);
+static_assert(std::invocable<rvalue_cv_function_object const volatile, int*>);
+static_assert(!std::invocable<rvalue_cv_function_object&, int*>);
+static_assert(!std::invocable<rvalue_cv_function_object const&, int*>);
+static_assert(!std::invocable<rvalue_cv_function_object volatile&, int*>);
+static_assert(!std::invocable<rvalue_cv_function_object const volatile&, int*>);
+
+struct multiple_overloads {
+ bool operator()();
+ void operator()(int);
+ int operator()(double);
+};
+static_assert(std::invocable<multiple_overloads&>);
+static_assert(std::invocable<multiple_overloads&, short>);
+static_assert(std::invocable<multiple_overloads&, int>);
+static_assert(!std::invocable<multiple_overloads&, long>);
+static_assert(std::invocable<multiple_overloads&, double>);
+static_assert(std::invocable<multiple_overloads&, float>);
+static_assert(std::invocable<multiple_overloads&, short&>);
+static_assert(std::invocable<multiple_overloads&, int&>);
+static_assert(!std::invocable<multiple_overloads&, long&>);
+static_assert(std::invocable<multiple_overloads&, float&>);
+static_assert(std::invocable<multiple_overloads&, double&>);
+} // namespace function_objects
+
+namespace pointer_to_member_functions {
+// clang-format off
+ template<class Member, class T, class... Args>
+ [[nodiscard]] constexpr bool check_member_is_invocable()
{
- auto G = std::mt19937_64(
- std::chrono::high_resolution_clock().now().time_since_epoch().count());
- auto D = std::uniform_int_distribution<>();
- ModelsInvocable(D, G);
+ constexpr bool result = std::invocable<Member, T, Args...>;
+ using uncv_t = std::remove_cvref_t<T>;
+ static_assert(std::invocable<Member, uncv_t*, Args...> == result);
+ static_assert(std::invocable<Member, std::unique_ptr<uncv_t>, Args...> == result);
+ static_assert(std::invocable<Member, std::reference_wrapper<uncv_t>, Args...> == result);
+ static_assert(!std::invocable<Member, std::nullptr_t, Args...>);
+ static_assert(!std::invocable<Member, int, Args...>);
+ static_assert(!std::invocable<Member, int*, Args...>);
+ static_assert(!std::invocable<Member, double*, Args...>);
+ struct S2 {};
+ static_assert(!std::invocable<Member, S2*, Args...>);
+ return result;
}
- return 0;
+// clang-format on
+
+static_assert(check_member_is_invocable<int S::*, S>());
+static_assert(std::invocable<int S::*, S&>);
+static_assert(std::invocable<int S::*, S const&>);
+static_assert(std::invocable<int S::*, S volatile&>);
+static_assert(std::invocable<int S::*, S const volatile&>);
+static_assert(std::invocable<int S::*, S&&>);
+static_assert(std::invocable<int S::*, S const&&>);
+static_assert(std::invocable<int S::*, S volatile&&>);
+static_assert(std::invocable<int S::*, S const volatile&&>);
+
+static_assert(check_member_is_invocable<int (S::*)(int), S, int>());
+static_assert(!check_member_is_invocable<int (S::*)(int), S>());
+using unqualified = void (S::*)();
+static_assert(std::invocable<unqualified, S&>);
+static_assert(!std::invocable<unqualified, S const&>);
+static_assert(!std::invocable<unqualified, S volatile&>);
+static_assert(!std::invocable<unqualified, S const volatile&>);
+static_assert(std::invocable<unqualified, S&&>);
+static_assert(!std::invocable<unqualified, S const&&>);
+static_assert(!std::invocable<unqualified, S volatile&&>);
+static_assert(!std::invocable<unqualified, S const volatile&&>);
+
+static_assert(check_member_is_invocable<int (S::*)(double) const, S, double>());
+using const_qualified = void (S::*)() const;
+static_assert(std::invocable<const_qualified, S&>);
+static_assert(std::invocable<const_qualified, S const&>);
+static_assert(!std::invocable<const_qualified, S volatile&>);
+static_assert(!std::invocable<const_qualified, S const volatile&>);
+static_assert(std::invocable<const_qualified, S&&>);
+static_assert(std::invocable<const_qualified, S const&&>);
+static_assert(!std::invocable<const_qualified, S volatile&&>);
+static_assert(!std::invocable<const_qualified, S const volatile&&>);
+
+static_assert(
+ check_member_is_invocable<int (S::*)(double[]) volatile, S, double*>());
+using volatile_qualified = void (S::*)() volatile;
+static_assert(std::invocable<volatile_qualified, S&>);
+static_assert(!std::invocable<volatile_qualified, S const&>);
+static_assert(std::invocable<volatile_qualified, S volatile&>);
+static_assert(!std::invocable<volatile_qualified, S const volatile&>);
+static_assert(std::invocable<volatile_qualified, S&&>);
+static_assert(!std::invocable<volatile_qualified, S const&&>);
+static_assert(std::invocable<volatile_qualified, S volatile&&>);
+static_assert(!std::invocable<volatile_qualified, S const volatile&&>);
+
+static_assert(check_member_is_invocable<int (S::*)(int, S&) const volatile, S,
+ int, S&>());
+using cv_qualified = void (S::*)() const volatile;
+static_assert(std::invocable<cv_qualified, S&>);
+static_assert(std::invocable<cv_qualified, S const&>);
+static_assert(std::invocable<cv_qualified, S volatile&>);
+static_assert(std::invocable<cv_qualified, S const volatile&>);
+static_assert(std::invocable<cv_qualified, S&&>);
+static_assert(std::invocable<cv_qualified, S const&&>);
+static_assert(std::invocable<cv_qualified, S volatile&&>);
+static_assert(std::invocable<cv_qualified, S const volatile&&>);
+
+static_assert(check_member_is_invocable<int (S::*)() &, S&>());
+using lvalue_qualified = void (S::*)() &;
+static_assert(std::invocable<lvalue_qualified, S&>);
+static_assert(!std::invocable<lvalue_qualified, S const&>);
+static_assert(!std::invocable<lvalue_qualified, S volatile&>);
+static_assert(!std::invocable<lvalue_qualified, S const volatile&>);
+static_assert(!std::invocable<lvalue_qualified, S&&>);
+static_assert(!std::invocable<lvalue_qualified, S const&&>);
+static_assert(!std::invocable<lvalue_qualified, S volatile&&>);
+static_assert(!std::invocable<lvalue_qualified, S const volatile&&>);
+
+static_assert(check_member_is_invocable<int (S::*)() const&, S>());
+using lvalue_const_qualified = void (S::*)() const&;
+static_assert(std::invocable<lvalue_const_qualified, S&>);
+static_assert(std::invocable<lvalue_const_qualified, S const&>);
+static_assert(!std::invocable<lvalue_const_qualified, S volatile&>);
+static_assert(!std::invocable<lvalue_const_qualified, S const volatile&>);
+static_assert(std::invocable<lvalue_const_qualified, S&&>);
+static_assert(std::invocable<lvalue_const_qualified, S const&&>);
+static_assert(!std::invocable<lvalue_const_qualified, S volatile&&>);
+static_assert(!std::invocable<lvalue_const_qualified, S const volatile&&>);
+
+static_assert(check_member_is_invocable<int (S::*)() volatile&, S&>());
+using lvalue_volatile_qualified = void (S::*)() volatile&;
+static_assert(std::invocable<lvalue_volatile_qualified, S&>);
+static_assert(!std::invocable<lvalue_volatile_qualified, S const&>);
+static_assert(std::invocable<lvalue_volatile_qualified, S volatile&>);
+static_assert(!std::invocable<lvalue_volatile_qualified, S const volatile&>);
+static_assert(!std::invocable<lvalue_volatile_qualified, S&&>);
+static_assert(!std::invocable<lvalue_volatile_qualified, S const&&>);
+static_assert(!std::invocable<lvalue_volatile_qualified, S volatile&&>);
+static_assert(!std::invocable<lvalue_volatile_qualified, S const volatile&&>);
+
+static_assert(check_member_is_invocable<int (S::*)() const volatile&, S&>());
+using lvalue_cv_qualified = void (S::*)() const volatile&;
+static_assert(std::invocable<lvalue_cv_qualified, S&>);
+static_assert(std::invocable<lvalue_cv_qualified, S const&>);
+static_assert(std::invocable<lvalue_cv_qualified, S volatile&>);
+static_assert(std::invocable<lvalue_cv_qualified, S const volatile&>);
+static_assert(!std::invocable<lvalue_cv_qualified, S&&>);
+static_assert(!std::invocable<lvalue_cv_qualified, S const&&>);
+static_assert(!std::invocable<lvalue_cv_qualified, S volatile&&>);
+static_assert(!std::invocable<lvalue_cv_qualified, S const volatile&&>);
+
+using rvalue_unqualified = void (S::*)() &&;
+static_assert(!std::invocable<rvalue_unqualified, S&>);
+static_assert(!std::invocable<rvalue_unqualified, S const&>);
+static_assert(!std::invocable<rvalue_unqualified, S volatile&>);
+static_assert(!std::invocable<rvalue_unqualified, S const volatile&>);
+static_assert(std::invocable<rvalue_unqualified, S&&>);
+static_assert(!std::invocable<rvalue_unqualified, S const&&>);
+static_assert(!std::invocable<rvalue_unqualified, S volatile&&>);
+static_assert(!std::invocable<rvalue_unqualified, S const volatile&&>);
+
+using rvalue_const_unqualified = void (S::*)() const&&;
+static_assert(!std::invocable<rvalue_const_unqualified, S&>);
+static_assert(!std::invocable<rvalue_const_unqualified, S const&>);
+static_assert(!std::invocable<rvalue_const_unqualified, S volatile&>);
+static_assert(!std::invocable<rvalue_const_unqualified, S const volatile&>);
+static_assert(std::invocable<rvalue_const_unqualified, S&&>);
+static_assert(std::invocable<rvalue_const_unqualified, S const&&>);
+static_assert(!std::invocable<rvalue_const_unqualified, S volatile&&>);
+static_assert(!std::invocable<rvalue_const_unqualified, S const volatile&&>);
+
+using rvalue_volatile_unqualified = void (S::*)() volatile&&;
+static_assert(!std::invocable<rvalue_volatile_unqualified, S&>);
+static_assert(!std::invocable<rvalue_volatile_unqualified, S const&>);
+static_assert(!std::invocable<rvalue_volatile_unqualified, S volatile&>);
+static_assert(!std::invocable<rvalue_volatile_unqualified, S const volatile&>);
+static_assert(std::invocable<rvalue_volatile_unqualified, S&&>);
+static_assert(!std::invocable<rvalue_volatile_unqualified, S const&&>);
+static_assert(std::invocable<rvalue_volatile_unqualified, S volatile&&>);
+static_assert(!std::invocable<rvalue_volatile_unqualified, S const volatile&&>);
+
+using rvalue_cv_unqualified = void (S::*)() const volatile&&;
+static_assert(!std::invocable<rvalue_cv_unqualified, S&>);
+static_assert(!std::invocable<rvalue_cv_unqualified, S const&>);
+static_assert(!std::invocable<rvalue_cv_unqualified, S volatile&>);
+static_assert(!std::invocable<rvalue_cv_unqualified, S const volatile&>);
+static_assert(std::invocable<rvalue_cv_unqualified, S&&>);
+static_assert(std::invocable<rvalue_cv_unqualified, S const&&>);
+static_assert(std::invocable<rvalue_cv_unqualified, S volatile&&>);
+static_assert(std::invocable<rvalue_cv_unqualified, S const volatile&&>);
+} // namespace pointer_to_member_functions
+
+// std::invocable-specific
+static_assert(
+ std::invocable<std::uniform_int_distribution<>, std::mt19937_64&>);
+
+[[nodiscard]] constexpr bool check_lambda(auto, auto...) { return false; }
+
+// clang-format off
+template<class F, class... Args>
+requires std::invocable<F, Args...>
+[[nodiscard]] constexpr bool check_lambda(F, Args&&...)
+{
+ return true;
}
+// clang-format on
+
+[[nodiscard]] constexpr bool check_lambdas() {
+ static_assert(check_lambda([] {}));
+ static_assert(check_lambda([](int) {}, 0));
+ static_assert(check_lambda([](int) {}, 0L));
+ static_assert(!check_lambda([](int) {}, nullptr));
+
+ int i = 0;
+ return check_lambda([](int&) {}, i);
+}
+
+static_assert(check_lambdas());
+
+int main(int, char**) { return 0; }
diff --git a/libcxx/test/std/concepts/concepts.callable/concept.regularinvocable/regular_invocable.pass.cpp b/libcxx/test/std/concepts/concepts.callable/concept.regularinvocable/regular_invocable.pass.cpp
index 3912504d5066..dd5d34c348c5 100644
--- a/libcxx/test/std/concepts/concepts.callable/concept.regularinvocable/regular_invocable.pass.cpp
+++ b/libcxx/test/std/concepts/concepts.callable/concept.regularinvocable/regular_invocable.pass.cpp
@@ -12,22 +12,49 @@
// template<class T, class U>
// concept regular_invocable;
+#include <chrono>
#include <concepts>
#include <memory>
#include <random>
#include <type_traits>
-#include "../functions.h"
+template <class R, class... Args>
+[[nodiscard]] constexpr bool check_invocable() {
+ constexpr bool result = std::regular_invocable<R(Args...), Args...>;
+ static_assert(std::regular_invocable<R(Args...) noexcept, Args...> == result);
+ static_assert(std::regular_invocable<R (*)(Args...), Args...> == result);
+ static_assert(std::regular_invocable<R (*)(Args...) noexcept, Args...> ==
+ result);
+ static_assert(std::regular_invocable<R (&)(Args...), Args...> == result);
+ static_assert(std::regular_invocable<R (&)(Args...) noexcept, Args...> ==
+ result);
-// clang-format off
-template <class F, class... Args>
-requires std::regular_invocable<F, Args...>
-constexpr void ModelsRegularInvocable(F, Args&&...) noexcept {}
+ return result;
+}
-template <class F, class... Args>
-requires (!std::regular_invocable<F, Args...>)
-constexpr void NotRegularInvocable(F, Args&&...) noexcept {}
-// clang-format on
+static_assert(check_invocable<void>());
+static_assert(check_invocable<void, int>());
+static_assert(check_invocable<void, int&>());
+static_assert(check_invocable<void, int*, double>());
+static_assert(check_invocable<int>());
+static_assert(check_invocable<int, int[]>());
+
+struct S;
+static_assert(check_invocable<int, int S::*, std::nullptr_t>());
+static_assert(check_invocable<int, int (S::*)(), int (S::*)(int), int>());
+static_assert(std::regular_invocable<void (*)(int const&), int&>);
+static_assert(std::regular_invocable<void (*)(int const&), int&&>);
+static_assert(std::regular_invocable<void (*)(int volatile&), int&>);
+static_assert(std::regular_invocable<void (*)(int const volatile&), int&>);
+
+static_assert(!std::regular_invocable<void(), int>);
+static_assert(!std::regular_invocable<void(int)>);
+static_assert(!std::regular_invocable<void(int*), double*>);
+static_assert(!std::regular_invocable<void (*)(int&), double*>);
+static_assert(std::regular_invocable<int S::*, std::unique_ptr<S> >);
+static_assert(std::regular_invocable<int S::*, std::shared_ptr<S> >);
+static_assert(!std::regular_invocable<void (*)(int&&), int&>);
+static_assert(!std::regular_invocable<void (*)(int&&), int const&>);
static_assert(!std::regular_invocable<void>);
static_assert(!std::regular_invocable<void*>);
@@ -35,84 +62,411 @@ static_assert(!std::regular_invocable<int>);
static_assert(!std::regular_invocable<int&>);
static_assert(!std::regular_invocable<int&&>);
-int main(int, char**) {
- {
- using namespace RegularInvocable;
-
- ModelsRegularInvocable(F);
- NotRegularInvocable(F, 0);
-
- ModelsRegularInvocable(G, 2);
- NotRegularInvocable(G);
- NotRegularInvocable(G, 3, 0);
-
- NotRegularInvocable(&A::I);
- NotRegularInvocable(&A::F);
-
- {
- A X;
- ModelsRegularInvocable(&A::I, X);
- ModelsRegularInvocable(&A::F, X);
- ModelsRegularInvocable(&A::G, X, 0);
- NotRegularInvocable(&A::G, X);
- NotRegularInvocable(&A::G, 0);
- NotRegularInvocable(&A::H);
-
- A const& Y = X;
- ModelsRegularInvocable(&A::I, Y);
- ModelsRegularInvocable(&A::F, Y);
- NotRegularInvocable(&A::G, Y, 0);
- NotRegularInvocable(&A::H, Y, 0);
- }
-
- ModelsRegularInvocable(&A::I, A{});
- ModelsRegularInvocable(&A::F, A{});
- ModelsRegularInvocable(&A::G, A{}, 0);
- ModelsRegularInvocable(&A::H, A{}, 0);
-
- {
- auto Up = std::make_unique<A>();
- ModelsRegularInvocable(&A::I, Up);
- ModelsRegularInvocable(&A::F, Up);
- ModelsRegularInvocable(&A::G, Up, 0);
- NotRegularInvocable(&A::H, Up, 0);
- }
- {
- auto Sp = std::make_shared<A>();
- ModelsRegularInvocable(&A::I, Sp);
- ModelsRegularInvocable(&A::F, Sp);
- ModelsRegularInvocable(&A::G, Sp, 0);
- NotRegularInvocable(&A::H, Sp, 0);
- }
- }
+namespace function_objects {
+struct function_object {
+ void operator()();
+};
+static_assert(std::regular_invocable<function_object>);
+static_assert(!std::regular_invocable<function_object const>);
+static_assert(!std::regular_invocable<function_object volatile>);
+static_assert(!std::regular_invocable<function_object const volatile>);
+static_assert(std::regular_invocable<function_object&>);
+static_assert(!std::regular_invocable<function_object const&>);
+static_assert(!std::regular_invocable<function_object volatile&>);
+static_assert(!std::regular_invocable<function_object const volatile&>);
+
+struct const_function_object {
+ void operator()(int) const;
+};
+static_assert(std::regular_invocable<const_function_object, int>);
+static_assert(std::regular_invocable<const_function_object const, int>);
+static_assert(!std::regular_invocable<const_function_object volatile, int>);
+static_assert(
+ !std::regular_invocable<const_function_object const volatile, int>);
+static_assert(std::regular_invocable<const_function_object&, int>);
+static_assert(std::regular_invocable<const_function_object const&, int>);
+static_assert(!std::regular_invocable<const_function_object volatile&, int>);
+static_assert(
+ !std::regular_invocable<const_function_object const volatile&, int>);
+
+struct volatile_function_object {
+ void operator()(int, int) volatile;
+};
+static_assert(std::regular_invocable<volatile_function_object, int, int>);
+static_assert(
+ !std::regular_invocable<volatile_function_object const, int, int>);
+static_assert(
+ std::regular_invocable<volatile_function_object volatile, int, int>);
+static_assert(
+ !std::regular_invocable<volatile_function_object const volatile, int, int>);
+static_assert(std::regular_invocable<volatile_function_object&, int, int>);
+static_assert(
+ !std::regular_invocable<volatile_function_object const&, int, int>);
+static_assert(
+ std::regular_invocable<volatile_function_object volatile&, int, int>);
+static_assert(!std::regular_invocable<volatile_function_object const volatile&,
+ int, int>);
+
+struct cv_function_object {
+ void operator()(int[]) const volatile;
+};
+static_assert(std::regular_invocable<cv_function_object, int*>);
+static_assert(std::regular_invocable<cv_function_object const, int*>);
+static_assert(std::regular_invocable<cv_function_object volatile, int*>);
+static_assert(std::regular_invocable<cv_function_object const volatile, int*>);
+static_assert(std::regular_invocable<cv_function_object&, int*>);
+static_assert(std::regular_invocable<cv_function_object const&, int*>);
+static_assert(std::regular_invocable<cv_function_object volatile&, int*>);
+static_assert(std::regular_invocable<cv_function_object const volatile&, int*>);
+
+struct lvalue_function_object {
+ void operator()() &;
+};
+static_assert(!std::regular_invocable<lvalue_function_object>);
+static_assert(!std::regular_invocable<lvalue_function_object const>);
+static_assert(!std::regular_invocable<lvalue_function_object volatile>);
+static_assert(!std::regular_invocable<lvalue_function_object const volatile>);
+static_assert(std::regular_invocable<lvalue_function_object&>);
+static_assert(!std::regular_invocable<lvalue_function_object const&>);
+static_assert(!std::regular_invocable<lvalue_function_object volatile&>);
+static_assert(!std::regular_invocable<lvalue_function_object const volatile&>);
+
+struct lvalue_const_function_object {
+ void operator()(int) const&;
+};
+static_assert(std::regular_invocable<lvalue_const_function_object, int>);
+static_assert(std::regular_invocable<lvalue_const_function_object const, int>);
+static_assert(
+ !std::regular_invocable<lvalue_const_function_object volatile, int>);
+static_assert(
+ !std::regular_invocable<lvalue_const_function_object const volatile, int>);
+static_assert(std::regular_invocable<lvalue_const_function_object&, int>);
+static_assert(std::regular_invocable<lvalue_const_function_object const&, int>);
+static_assert(
+ !std::regular_invocable<lvalue_const_function_object volatile&, int>);
+static_assert(
+ !std::regular_invocable<lvalue_const_function_object const volatile&, int>);
+
+struct lvalue_volatile_function_object {
+ void operator()(int, int) volatile&;
+};
+static_assert(
+ !std::regular_invocable<lvalue_volatile_function_object, int, int>);
+static_assert(
+ !std::regular_invocable<lvalue_volatile_function_object const, int, int>);
+static_assert(!std::regular_invocable<lvalue_volatile_function_object volatile,
+ int, int>);
+static_assert(!std::regular_invocable<
+ lvalue_volatile_function_object const volatile, int, int>);
+static_assert(
+ std::regular_invocable<lvalue_volatile_function_object&, int, int>);
+static_assert(
+ !std::regular_invocable<lvalue_volatile_function_object const&, int, int>);
+static_assert(std::regular_invocable<lvalue_volatile_function_object volatile&,
+ int, int>);
+static_assert(!std::regular_invocable<
+ lvalue_volatile_function_object const volatile&, int, int>);
+
+struct lvalue_cv_function_object {
+ void operator()(int[]) const volatile&;
+};
+static_assert(!std::regular_invocable<lvalue_cv_function_object, int*>);
+static_assert(!std::regular_invocable<lvalue_cv_function_object const, int*>);
+static_assert(
+ !std::regular_invocable<lvalue_cv_function_object volatile, int*>);
+static_assert(
+ !std::regular_invocable<lvalue_cv_function_object const volatile, int*>);
+static_assert(std::regular_invocable<lvalue_cv_function_object&, int*>);
+static_assert(std::regular_invocable<lvalue_cv_function_object const&, int*>);
+static_assert(
+ std::regular_invocable<lvalue_cv_function_object volatile&, int*>);
+static_assert(
+ std::regular_invocable<lvalue_cv_function_object const volatile&, int*>);
+//
+struct rvalue_function_object {
+ void operator()() &&;
+};
+static_assert(std::regular_invocable<rvalue_function_object>);
+static_assert(!std::regular_invocable<rvalue_function_object const>);
+static_assert(!std::regular_invocable<rvalue_function_object volatile>);
+static_assert(!std::regular_invocable<rvalue_function_object const volatile>);
+static_assert(!std::regular_invocable<rvalue_function_object&>);
+static_assert(!std::regular_invocable<rvalue_function_object const&>);
+static_assert(!std::regular_invocable<rvalue_function_object volatile&>);
+static_assert(!std::regular_invocable<rvalue_function_object const volatile&>);
+
+struct rvalue_const_function_object {
+ void operator()(int) const&&;
+};
+static_assert(std::regular_invocable<rvalue_const_function_object, int>);
+static_assert(std::regular_invocable<rvalue_const_function_object const, int>);
+static_assert(
+ !std::regular_invocable<rvalue_const_function_object volatile, int>);
+static_assert(
+ !std::regular_invocable<rvalue_const_function_object const volatile, int>);
+static_assert(!std::regular_invocable<rvalue_const_function_object&, int>);
+static_assert(
+ !std::regular_invocable<rvalue_const_function_object const&, int>);
+static_assert(
+ !std::regular_invocable<rvalue_const_function_object volatile&, int>);
+static_assert(
+ !std::regular_invocable<rvalue_const_function_object const volatile&, int>);
+
+struct rvalue_volatile_function_object {
+ void operator()(int, int) volatile&&;
+};
+static_assert(
+ std::regular_invocable<rvalue_volatile_function_object, int, int>);
+static_assert(
+ !std::regular_invocable<rvalue_volatile_function_object const, int, int>);
+static_assert(
+ std::regular_invocable<rvalue_volatile_function_object volatile, int, int>);
+static_assert(!std::regular_invocable<
+ rvalue_volatile_function_object const volatile, int, int>);
+static_assert(
+ !std::regular_invocable<rvalue_volatile_function_object&, int, int>);
+static_assert(
+ !std::regular_invocable<rvalue_volatile_function_object const&, int, int>);
+static_assert(!std::regular_invocable<rvalue_volatile_function_object volatile&,
+ int, int>);
+static_assert(!std::regular_invocable<
+ rvalue_volatile_function_object const volatile&, int, int>);
+
+struct rvalue_cv_function_object {
+ void operator()(int[]) const volatile&&;
+};
+static_assert(std::regular_invocable<rvalue_cv_function_object, int*>);
+static_assert(std::regular_invocable<rvalue_cv_function_object const, int*>);
+static_assert(std::regular_invocable<rvalue_cv_function_object volatile, int*>);
+static_assert(
+ std::regular_invocable<rvalue_cv_function_object const volatile, int*>);
+static_assert(!std::regular_invocable<rvalue_cv_function_object&, int*>);
+static_assert(!std::regular_invocable<rvalue_cv_function_object const&, int*>);
+static_assert(
+ !std::regular_invocable<rvalue_cv_function_object volatile&, int*>);
+static_assert(
+ !std::regular_invocable<rvalue_cv_function_object const volatile&, int*>);
+
+struct multiple_overloads {
+ bool operator()();
+ void operator()(int);
+ int operator()(double);
+};
+static_assert(std::regular_invocable<multiple_overloads&>);
+static_assert(std::regular_invocable<multiple_overloads&, short>);
+static_assert(std::regular_invocable<multiple_overloads&, int>);
+static_assert(!std::regular_invocable<multiple_overloads&, long>);
+static_assert(std::regular_invocable<multiple_overloads&, double>);
+static_assert(std::regular_invocable<multiple_overloads&, float>);
+static_assert(std::regular_invocable<multiple_overloads&, short&>);
+static_assert(std::regular_invocable<multiple_overloads&, int&>);
+static_assert(!std::regular_invocable<multiple_overloads&, long&>);
+static_assert(std::regular_invocable<multiple_overloads&, float&>);
+static_assert(std::regular_invocable<multiple_overloads&, double&>);
+} // namespace function_objects
+
+namespace pointer_to_member_functions {
+// clang-format off
+ template<class Member, class T, class... Args>
+ [[nodiscard]] constexpr bool check_member_is_invocable()
{
- using namespace Predicate;
- {
- ModelsRegularInvocable(L2rSorted{}, 0, 1, 2);
- NotRegularInvocable(L2rSorted{});
- NotRegularInvocable(L2rSorted{}, 0);
- NotRegularInvocable(L2rSorted{}, 0, 1);
- }
- {
- auto Up = std::make_unique<L2rSorted>();
- ModelsRegularInvocable(&L2rSorted::operator()<int>, Up, 0, 1, 2);
- NotRegularInvocable(&L2rSorted::operator()<int>, Up);
- NotRegularInvocable(&L2rSorted::operator()<int>, Up, 0);
- NotRegularInvocable(&L2rSorted::operator()<int>, Up, 0, 1);
- }
- {
- auto Sp = std::make_shared<L2rSorted>();
- ModelsRegularInvocable(&L2rSorted::operator()<int>, Sp, 0, 1, 2);
- NotRegularInvocable(&L2rSorted::operator()<int>, Sp);
- NotRegularInvocable(&L2rSorted::operator()<int>, Sp, 0);
- NotRegularInvocable(&L2rSorted::operator()<int>, Sp, 0, 1);
- }
+ constexpr bool result = std::regular_invocable<Member, T, Args...>;
+ using uncv_t = std::remove_cvref_t<T>;
+ static_assert(std::regular_invocable<Member, uncv_t*, Args...> == result);
+ static_assert(std::regular_invocable<Member, std::unique_ptr<uncv_t>, Args...> == result);
+ static_assert(std::regular_invocable<Member, std::reference_wrapper<uncv_t>, Args...> == result);
+ static_assert(!std::regular_invocable<Member, std::nullptr_t, Args...>);
+ static_assert(!std::regular_invocable<Member, int, Args...>);
+ static_assert(!std::regular_invocable<Member, int*, Args...>);
+ static_assert(!std::regular_invocable<Member, double*, Args...>);
+ struct S2 {};
+ static_assert(!std::regular_invocable<Member, S2*, Args...>);
+ return result;
}
- // {
- // RNG doesn't model regular_invocable, left here for documentation
- // auto G = std::mt19937_64(std::random_device()());
- // auto D = std::uniform_int_distribution<>();
- // models_invocable(D, G);
- // }
- return 0;
+// clang-format on
+
+static_assert(check_member_is_invocable<int S::*, S>());
+static_assert(std::regular_invocable<int S::*, S&>);
+static_assert(std::regular_invocable<int S::*, S const&>);
+static_assert(std::regular_invocable<int S::*, S volatile&>);
+static_assert(std::regular_invocable<int S::*, S const volatile&>);
+static_assert(std::regular_invocable<int S::*, S&&>);
+static_assert(std::regular_invocable<int S::*, S const&&>);
+static_assert(std::regular_invocable<int S::*, S volatile&&>);
+static_assert(std::regular_invocable<int S::*, S const volatile&&>);
+
+static_assert(check_member_is_invocable<int (S::*)(int), S, int>());
+static_assert(!check_member_is_invocable<int (S::*)(int), S>());
+using unqualified = void (S::*)();
+static_assert(std::regular_invocable<unqualified, S&>);
+static_assert(!std::regular_invocable<unqualified, S const&>);
+static_assert(!std::regular_invocable<unqualified, S volatile&>);
+static_assert(!std::regular_invocable<unqualified, S const volatile&>);
+static_assert(std::regular_invocable<unqualified, S&&>);
+static_assert(!std::regular_invocable<unqualified, S const&&>);
+static_assert(!std::regular_invocable<unqualified, S volatile&&>);
+static_assert(!std::regular_invocable<unqualified, S const volatile&&>);
+
+static_assert(check_member_is_invocable<int (S::*)(double) const, S, double>());
+using const_qualified = void (S::*)() const;
+static_assert(std::regular_invocable<const_qualified, S&>);
+static_assert(std::regular_invocable<const_qualified, S const&>);
+static_assert(!std::regular_invocable<const_qualified, S volatile&>);
+static_assert(!std::regular_invocable<const_qualified, S const volatile&>);
+static_assert(std::regular_invocable<const_qualified, S&&>);
+static_assert(std::regular_invocable<const_qualified, S const&&>);
+static_assert(!std::regular_invocable<const_qualified, S volatile&&>);
+static_assert(!std::regular_invocable<const_qualified, S const volatile&&>);
+
+static_assert(
+ check_member_is_invocable<int (S::*)(double[]) volatile, S, double*>());
+using volatile_qualified = void (S::*)() volatile;
+static_assert(std::regular_invocable<volatile_qualified, S&>);
+static_assert(!std::regular_invocable<volatile_qualified, S const&>);
+static_assert(std::regular_invocable<volatile_qualified, S volatile&>);
+static_assert(!std::regular_invocable<volatile_qualified, S const volatile&>);
+static_assert(std::regular_invocable<volatile_qualified, S&&>);
+static_assert(!std::regular_invocable<volatile_qualified, S const&&>);
+static_assert(std::regular_invocable<volatile_qualified, S volatile&&>);
+static_assert(!std::regular_invocable<volatile_qualified, S const volatile&&>);
+
+static_assert(check_member_is_invocable<int (S::*)(int, S&) const volatile, S,
+ int, S&>());
+using cv_qualified = void (S::*)() const volatile;
+static_assert(std::regular_invocable<cv_qualified, S&>);
+static_assert(std::regular_invocable<cv_qualified, S const&>);
+static_assert(std::regular_invocable<cv_qualified, S volatile&>);
+static_assert(std::regular_invocable<cv_qualified, S const volatile&>);
+static_assert(std::regular_invocable<cv_qualified, S&&>);
+static_assert(std::regular_invocable<cv_qualified, S const&&>);
+static_assert(std::regular_invocable<cv_qualified, S volatile&&>);
+static_assert(std::regular_invocable<cv_qualified, S const volatile&&>);
+
+static_assert(check_member_is_invocable<int (S::*)() &, S&>());
+using lvalue_qualified = void (S::*)() &;
+static_assert(std::regular_invocable<lvalue_qualified, S&>);
+static_assert(!std::regular_invocable<lvalue_qualified, S const&>);
+static_assert(!std::regular_invocable<lvalue_qualified, S volatile&>);
+static_assert(!std::regular_invocable<lvalue_qualified, S const volatile&>);
+static_assert(!std::regular_invocable<lvalue_qualified, S&&>);
+static_assert(!std::regular_invocable<lvalue_qualified, S const&&>);
+static_assert(!std::regular_invocable<lvalue_qualified, S volatile&&>);
+static_assert(!std::regular_invocable<lvalue_qualified, S const volatile&&>);
+
+static_assert(check_member_is_invocable<int (S::*)() const&, S>());
+using lvalue_const_qualified = void (S::*)() const&;
+static_assert(std::regular_invocable<lvalue_const_qualified, S&>);
+static_assert(std::regular_invocable<lvalue_const_qualified, S const&>);
+static_assert(!std::regular_invocable<lvalue_const_qualified, S volatile&>);
+static_assert(
+ !std::regular_invocable<lvalue_const_qualified, S const volatile&>);
+static_assert(std::regular_invocable<lvalue_const_qualified, S&&>);
+static_assert(std::regular_invocable<lvalue_const_qualified, S const&&>);
+static_assert(!std::regular_invocable<lvalue_const_qualified, S volatile&&>);
+static_assert(
+ !std::regular_invocable<lvalue_const_qualified, S const volatile&&>);
+
+static_assert(check_member_is_invocable<int (S::*)() volatile&, S&>());
+using lvalue_volatile_qualified = void (S::*)() volatile&;
+static_assert(std::regular_invocable<lvalue_volatile_qualified, S&>);
+static_assert(!std::regular_invocable<lvalue_volatile_qualified, S const&>);
+static_assert(std::regular_invocable<lvalue_volatile_qualified, S volatile&>);
+static_assert(
+ !std::regular_invocable<lvalue_volatile_qualified, S const volatile&>);
+static_assert(!std::regular_invocable<lvalue_volatile_qualified, S&&>);
+static_assert(!std::regular_invocable<lvalue_volatile_qualified, S const&&>);
+static_assert(!std::regular_invocable<lvalue_volatile_qualified, S volatile&&>);
+static_assert(
+ !std::regular_invocable<lvalue_volatile_qualified, S const volatile&&>);
+
+static_assert(check_member_is_invocable<int (S::*)() const volatile&, S&>());
+using lvalue_cv_qualified = void (S::*)() const volatile&;
+static_assert(std::regular_invocable<lvalue_cv_qualified, S&>);
+static_assert(std::regular_invocable<lvalue_cv_qualified, S const&>);
+static_assert(std::regular_invocable<lvalue_cv_qualified, S volatile&>);
+static_assert(std::regular_invocable<lvalue_cv_qualified, S const volatile&>);
+static_assert(!std::regular_invocable<lvalue_cv_qualified, S&&>);
+static_assert(!std::regular_invocable<lvalue_cv_qualified, S const&&>);
+static_assert(!std::regular_invocable<lvalue_cv_qualified, S volatile&&>);
+static_assert(!std::regular_invocable<lvalue_cv_qualified, S const volatile&&>);
+
+using rvalue_unqualified = void (S::*)() &&;
+static_assert(!std::regular_invocable<rvalue_unqualified, S&>);
+static_assert(!std::regular_invocable<rvalue_unqualified, S const&>);
+static_assert(!std::regular_invocable<rvalue_unqualified, S volatile&>);
+static_assert(!std::regular_invocable<rvalue_unqualified, S const volatile&>);
+static_assert(std::regular_invocable<rvalue_unqualified, S&&>);
+static_assert(!std::regular_invocable<rvalue_unqualified, S const&&>);
+static_assert(!std::regular_invocable<rvalue_unqualified, S volatile&&>);
+static_assert(!std::regular_invocable<rvalue_unqualified, S const volatile&&>);
+
+using rvalue_const_unqualified = void (S::*)() const&&;
+static_assert(!std::regular_invocable<rvalue_const_unqualified, S&>);
+static_assert(!std::regular_invocable<rvalue_const_unqualified, S const&>);
+static_assert(!std::regular_invocable<rvalue_const_unqualified, S volatile&>);
+static_assert(
+ !std::regular_invocable<rvalue_const_unqualified, S const volatile&>);
+static_assert(std::regular_invocable<rvalue_const_unqualified, S&&>);
+static_assert(std::regular_invocable<rvalue_const_unqualified, S const&&>);
+static_assert(!std::regular_invocable<rvalue_const_unqualified, S volatile&&>);
+static_assert(
+ !std::regular_invocable<rvalue_const_unqualified, S const volatile&&>);
+
+using rvalue_volatile_unqualified = void (S::*)() volatile&&;
+static_assert(!std::regular_invocable<rvalue_volatile_unqualified, S&>);
+static_assert(!std::regular_invocable<rvalue_volatile_unqualified, S const&>);
+static_assert(
+ !std::regular_invocable<rvalue_volatile_unqualified, S volatile&>);
+static_assert(
+ !std::regular_invocable<rvalue_volatile_unqualified, S const volatile&>);
+static_assert(std::regular_invocable<rvalue_volatile_unqualified, S&&>);
+static_assert(!std::regular_invocable<rvalue_volatile_unqualified, S const&&>);
+static_assert(
+ std::regular_invocable<rvalue_volatile_unqualified, S volatile&&>);
+static_assert(
+ !std::regular_invocable<rvalue_volatile_unqualified, S const volatile&&>);
+
+using rvalue_cv_unqualified = void (S::*)() const volatile&&;
+static_assert(!std::regular_invocable<rvalue_cv_unqualified, S&>);
+static_assert(!std::regular_invocable<rvalue_cv_unqualified, S const&>);
+static_assert(!std::regular_invocable<rvalue_cv_unqualified, S volatile&>);
+static_assert(
+ !std::regular_invocable<rvalue_cv_unqualified, S const volatile&>);
+static_assert(std::regular_invocable<rvalue_cv_unqualified, S&&>);
+static_assert(std::regular_invocable<rvalue_cv_unqualified, S const&&>);
+static_assert(std::regular_invocable<rvalue_cv_unqualified, S volatile&&>);
+static_assert(
+ std::regular_invocable<rvalue_cv_unqualified, S const volatile&&>);
+} // namespace pointer_to_member_functions
+
+[[nodiscard]] constexpr bool check_lambda(auto, auto...) { return false; }
+
+// clang-format off
+template<class F, class... Args>
+requires std::invocable<F, Args...>
+[[nodiscard]] constexpr bool check_lambda(F, Args&&...)
+{
+ return false;
}
+
+template<class F, class... Args>
+requires std::regular_invocable<F, Args...> && true
+[[nodiscard]] constexpr bool check_lambda(F, Args&&...)
+{
+ return true;
+}
+// clang-format on
+
+[[nodiscard]] constexpr bool check_lambdas() {
+ static_assert(check_lambda([] {}));
+ static_assert(check_lambda([](int) {}, 0));
+ static_assert(check_lambda([](int) {}, 0L));
+ static_assert(!check_lambda([](int) {}, nullptr));
+
+ int i = 0;
+ return check_lambda([](int&) {}, i);
+}
+
+static_assert(check_lambdas());
+
+int main(int, char**) { return 0; }
diff --git a/libcxx/test/std/concepts/concepts.callable/functions.h b/libcxx/test/std/concepts/concepts.callable/functions.h
deleted file mode 100644
index bf77e44f15da..000000000000
--- a/libcxx/test/std/concepts/concepts.callable/functions.h
+++ /dev/null
@@ -1,40 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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_FUNCTIONS_H
-#define CALLABLE_FUNCTIONS_H
-
-namespace RegularInvocable {
-struct A {
- int I = 13;
- constexpr int F() const noexcept { return 42; }
- constexpr int G(int X) { return 2 * X + 1; }
- constexpr int H(int J) && { return I * J; }
-};
-
-constexpr int F() noexcept { return 13; }
-constexpr int G(int I) { return 2 * I + 1; }
-} // namespace RegularInvocable
-
-namespace Predicate {
-struct L2rSorted {
- template <class T>
- constexpr bool operator()(T const& A, T const& B, T const& C) const noexcept {
- return A <= B && B <= C;
- }
-};
-
-struct NotAPredicate {
- void operator()() const noexcept {}
-};
-} // namespace Predicate
-
-namespace Relation {
-int Greater(int X, int Y) noexcept { return X > Y; }
-} // namespace Relation
-
-#endif // CALLABLE_FUNCTIONS_H
More information about the libcxx-commits
mailing list