forked from OSchip/llvm-project
[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
This commit is contained in:
parent
c773d0f973
commit
e06f1a8e3c
|
@ -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**) {
|
||||
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()
|
||||
{
|
||||
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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
{
|
||||
auto G = std::mt19937_64(
|
||||
std::chrono::high_resolution_clock().now().time_since_epoch().count());
|
||||
auto D = std::uniform_int_distribution<>();
|
||||
ModelsInvocable(D, G);
|
||||
}
|
||||
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; }
|
||||
|
|
|
@ -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**) {
|
||||
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 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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
// {
|
||||
// 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; }
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue