131191e15SLouis Dionne //===----------------------------------------------------------------------===//
231191e15SLouis Dionne //
331191e15SLouis Dionne // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
431191e15SLouis Dionne // See https://llvm.org/LICENSE.txt for license information.
531191e15SLouis Dionne // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
631191e15SLouis Dionne //
731191e15SLouis Dionne //===----------------------------------------------------------------------===//
831191e15SLouis Dionne 
931191e15SLouis Dionne // UNSUPPORTED: c++03, c++11, c++14, c++17
1031191e15SLouis Dionne 
1131191e15SLouis Dionne // template<class T, class U>
1231191e15SLouis Dionne // concept regular_invocable;
1331191e15SLouis Dionne 
1431191e15SLouis Dionne #include <concepts>
15*e99c4906SNikolas Klauser #include <cstddef>
1634f73804SNikolas Klauser #include <functional>
1731191e15SLouis Dionne #include <memory>
1831191e15SLouis Dionne #include <type_traits>
1931191e15SLouis Dionne 
2031191e15SLouis Dionne template <class R, class... Args>
2188b73a98SLouis Dionne constexpr bool check_invocable() {
2231191e15SLouis Dionne   constexpr bool result = std::regular_invocable<R(Args...), Args...>;
2331191e15SLouis Dionne   static_assert(std::regular_invocable<R(Args...) noexcept, Args...> == result);
2431191e15SLouis Dionne   static_assert(std::regular_invocable<R (*)(Args...), Args...> == result);
2531191e15SLouis Dionne   static_assert(std::regular_invocable<R (*)(Args...) noexcept, Args...> ==
2631191e15SLouis Dionne                 result);
2731191e15SLouis Dionne   static_assert(std::regular_invocable<R (&)(Args...), Args...> == result);
2831191e15SLouis Dionne   static_assert(std::regular_invocable<R (&)(Args...) noexcept, Args...> ==
2931191e15SLouis Dionne                 result);
3031191e15SLouis Dionne 
3131191e15SLouis Dionne   return result;
3231191e15SLouis Dionne }
3331191e15SLouis Dionne 
3431191e15SLouis Dionne static_assert(check_invocable<void>());
3531191e15SLouis Dionne static_assert(check_invocable<void, int>());
3631191e15SLouis Dionne static_assert(check_invocable<void, int&>());
3731191e15SLouis Dionne static_assert(check_invocable<void, int*, double>());
3831191e15SLouis Dionne static_assert(check_invocable<int>());
3931191e15SLouis Dionne static_assert(check_invocable<int, int[]>());
4031191e15SLouis Dionne 
4131191e15SLouis Dionne struct S;
4231191e15SLouis Dionne static_assert(check_invocable<int, int S::*, std::nullptr_t>());
4331191e15SLouis Dionne static_assert(check_invocable<int, int (S::*)(), int (S::*)(int), int>());
4431191e15SLouis Dionne static_assert(std::regular_invocable<void (*)(int const&), int&>);
4531191e15SLouis Dionne static_assert(std::regular_invocable<void (*)(int const&), int&&>);
4631191e15SLouis Dionne static_assert(std::regular_invocable<void (*)(int volatile&), int&>);
4731191e15SLouis Dionne static_assert(std::regular_invocable<void (*)(int const volatile&), int&>);
4831191e15SLouis Dionne 
4931191e15SLouis Dionne static_assert(!std::regular_invocable<void(), int>);
5031191e15SLouis Dionne static_assert(!std::regular_invocable<void(int)>);
5131191e15SLouis Dionne static_assert(!std::regular_invocable<void(int*), double*>);
5231191e15SLouis Dionne static_assert(!std::regular_invocable<void (*)(int&), double*>);
5331191e15SLouis Dionne static_assert(std::regular_invocable<int S::*, std::unique_ptr<S> >);
5431191e15SLouis Dionne static_assert(std::regular_invocable<int S::*, std::shared_ptr<S> >);
5531191e15SLouis Dionne static_assert(!std::regular_invocable<void (*)(int&&), int&>);
5631191e15SLouis Dionne static_assert(!std::regular_invocable<void (*)(int&&), int const&>);
5731191e15SLouis Dionne 
5831191e15SLouis Dionne static_assert(!std::regular_invocable<void>);
5931191e15SLouis Dionne static_assert(!std::regular_invocable<void*>);
6031191e15SLouis Dionne static_assert(!std::regular_invocable<int>);
6131191e15SLouis Dionne static_assert(!std::regular_invocable<int&>);
6231191e15SLouis Dionne static_assert(!std::regular_invocable<int&&>);
6331191e15SLouis Dionne 
6431191e15SLouis Dionne namespace function_objects {
6531191e15SLouis Dionne struct function_object {
6631191e15SLouis Dionne   void operator()();
6731191e15SLouis Dionne };
6831191e15SLouis Dionne static_assert(std::regular_invocable<function_object>);
6931191e15SLouis Dionne static_assert(!std::regular_invocable<function_object const>);
7031191e15SLouis Dionne static_assert(!std::regular_invocable<function_object volatile>);
7131191e15SLouis Dionne static_assert(!std::regular_invocable<function_object const volatile>);
7231191e15SLouis Dionne static_assert(std::regular_invocable<function_object&>);
7331191e15SLouis Dionne static_assert(!std::regular_invocable<function_object const&>);
7431191e15SLouis Dionne static_assert(!std::regular_invocable<function_object volatile&>);
7531191e15SLouis Dionne static_assert(!std::regular_invocable<function_object const volatile&>);
7631191e15SLouis Dionne 
7731191e15SLouis Dionne struct const_function_object {
7831191e15SLouis Dionne   void operator()(int) const;
7931191e15SLouis Dionne };
8031191e15SLouis Dionne static_assert(std::regular_invocable<const_function_object, int>);
8131191e15SLouis Dionne static_assert(std::regular_invocable<const_function_object const, int>);
8231191e15SLouis Dionne static_assert(!std::regular_invocable<const_function_object volatile, int>);
8331191e15SLouis Dionne static_assert(
8431191e15SLouis Dionne     !std::regular_invocable<const_function_object const volatile, int>);
8531191e15SLouis Dionne static_assert(std::regular_invocable<const_function_object&, int>);
8631191e15SLouis Dionne static_assert(std::regular_invocable<const_function_object const&, int>);
8731191e15SLouis Dionne static_assert(!std::regular_invocable<const_function_object volatile&, int>);
8831191e15SLouis Dionne static_assert(
8931191e15SLouis Dionne     !std::regular_invocable<const_function_object const volatile&, int>);
9031191e15SLouis Dionne 
9131191e15SLouis Dionne struct volatile_function_object {
9231191e15SLouis Dionne   void operator()(int, int) volatile;
9331191e15SLouis Dionne };
9431191e15SLouis Dionne static_assert(std::regular_invocable<volatile_function_object, int, int>);
9531191e15SLouis Dionne static_assert(
9631191e15SLouis Dionne     !std::regular_invocable<volatile_function_object const, int, int>);
9731191e15SLouis Dionne static_assert(
9831191e15SLouis Dionne     std::regular_invocable<volatile_function_object volatile, int, int>);
9931191e15SLouis Dionne static_assert(
10031191e15SLouis Dionne     !std::regular_invocable<volatile_function_object const volatile, int, int>);
10131191e15SLouis Dionne static_assert(std::regular_invocable<volatile_function_object&, int, int>);
10231191e15SLouis Dionne static_assert(
10331191e15SLouis Dionne     !std::regular_invocable<volatile_function_object const&, int, int>);
10431191e15SLouis Dionne static_assert(
10531191e15SLouis Dionne     std::regular_invocable<volatile_function_object volatile&, int, int>);
10631191e15SLouis Dionne static_assert(!std::regular_invocable<volatile_function_object const volatile&,
10731191e15SLouis Dionne                                       int, int>);
10831191e15SLouis Dionne 
10931191e15SLouis Dionne struct cv_function_object {
11031191e15SLouis Dionne   void operator()(int[]) const volatile;
11131191e15SLouis Dionne };
11231191e15SLouis Dionne static_assert(std::regular_invocable<cv_function_object, int*>);
11331191e15SLouis Dionne static_assert(std::regular_invocable<cv_function_object const, int*>);
11431191e15SLouis Dionne static_assert(std::regular_invocable<cv_function_object volatile, int*>);
11531191e15SLouis Dionne static_assert(std::regular_invocable<cv_function_object const volatile, int*>);
11631191e15SLouis Dionne static_assert(std::regular_invocable<cv_function_object&, int*>);
11731191e15SLouis Dionne static_assert(std::regular_invocable<cv_function_object const&, int*>);
11831191e15SLouis Dionne static_assert(std::regular_invocable<cv_function_object volatile&, int*>);
11931191e15SLouis Dionne static_assert(std::regular_invocable<cv_function_object const volatile&, int*>);
12031191e15SLouis Dionne 
12131191e15SLouis Dionne struct lvalue_function_object {
12231191e15SLouis Dionne   void operator()() &;
12331191e15SLouis Dionne };
12431191e15SLouis Dionne static_assert(!std::regular_invocable<lvalue_function_object>);
12531191e15SLouis Dionne static_assert(!std::regular_invocable<lvalue_function_object const>);
12631191e15SLouis Dionne static_assert(!std::regular_invocable<lvalue_function_object volatile>);
12731191e15SLouis Dionne static_assert(!std::regular_invocable<lvalue_function_object const volatile>);
12831191e15SLouis Dionne static_assert(std::regular_invocable<lvalue_function_object&>);
12931191e15SLouis Dionne static_assert(!std::regular_invocable<lvalue_function_object const&>);
13031191e15SLouis Dionne static_assert(!std::regular_invocable<lvalue_function_object volatile&>);
13131191e15SLouis Dionne static_assert(!std::regular_invocable<lvalue_function_object const volatile&>);
13231191e15SLouis Dionne 
13331191e15SLouis Dionne struct lvalue_const_function_object {
13431191e15SLouis Dionne   void operator()(int) const&;
13531191e15SLouis Dionne };
13631191e15SLouis Dionne static_assert(std::regular_invocable<lvalue_const_function_object, int>);
13731191e15SLouis Dionne static_assert(std::regular_invocable<lvalue_const_function_object const, int>);
13831191e15SLouis Dionne static_assert(
13931191e15SLouis Dionne     !std::regular_invocable<lvalue_const_function_object volatile, int>);
14031191e15SLouis Dionne static_assert(
14131191e15SLouis Dionne     !std::regular_invocable<lvalue_const_function_object const volatile, int>);
14231191e15SLouis Dionne static_assert(std::regular_invocable<lvalue_const_function_object&, int>);
14331191e15SLouis Dionne static_assert(std::regular_invocable<lvalue_const_function_object const&, int>);
14431191e15SLouis Dionne static_assert(
14531191e15SLouis Dionne     !std::regular_invocable<lvalue_const_function_object volatile&, int>);
14631191e15SLouis Dionne static_assert(
14731191e15SLouis Dionne     !std::regular_invocable<lvalue_const_function_object const volatile&, int>);
14831191e15SLouis Dionne 
14931191e15SLouis Dionne struct lvalue_volatile_function_object {
15031191e15SLouis Dionne   void operator()(int, int) volatile&;
15131191e15SLouis Dionne };
15231191e15SLouis Dionne static_assert(
15331191e15SLouis Dionne     !std::regular_invocable<lvalue_volatile_function_object, int, int>);
15431191e15SLouis Dionne static_assert(
15531191e15SLouis Dionne     !std::regular_invocable<lvalue_volatile_function_object const, int, int>);
15631191e15SLouis Dionne static_assert(!std::regular_invocable<lvalue_volatile_function_object volatile,
15731191e15SLouis Dionne                                       int, int>);
15831191e15SLouis Dionne static_assert(!std::regular_invocable<
15931191e15SLouis Dionne               lvalue_volatile_function_object const volatile, int, int>);
16031191e15SLouis Dionne static_assert(
16131191e15SLouis Dionne     std::regular_invocable<lvalue_volatile_function_object&, int, int>);
16231191e15SLouis Dionne static_assert(
16331191e15SLouis Dionne     !std::regular_invocable<lvalue_volatile_function_object const&, int, int>);
16431191e15SLouis Dionne static_assert(std::regular_invocable<lvalue_volatile_function_object volatile&,
16531191e15SLouis Dionne                                      int, int>);
16631191e15SLouis Dionne static_assert(!std::regular_invocable<
16731191e15SLouis Dionne               lvalue_volatile_function_object const volatile&, int, int>);
16831191e15SLouis Dionne 
16931191e15SLouis Dionne struct lvalue_cv_function_object {
17031191e15SLouis Dionne   void operator()(int[]) const volatile&;
17131191e15SLouis Dionne };
17231191e15SLouis Dionne static_assert(!std::regular_invocable<lvalue_cv_function_object, int*>);
17331191e15SLouis Dionne static_assert(!std::regular_invocable<lvalue_cv_function_object const, int*>);
17431191e15SLouis Dionne static_assert(
17531191e15SLouis Dionne     !std::regular_invocable<lvalue_cv_function_object volatile, int*>);
17631191e15SLouis Dionne static_assert(
17731191e15SLouis Dionne     !std::regular_invocable<lvalue_cv_function_object const volatile, int*>);
17831191e15SLouis Dionne static_assert(std::regular_invocable<lvalue_cv_function_object&, int*>);
17931191e15SLouis Dionne static_assert(std::regular_invocable<lvalue_cv_function_object const&, int*>);
18031191e15SLouis Dionne static_assert(
18131191e15SLouis Dionne     std::regular_invocable<lvalue_cv_function_object volatile&, int*>);
18231191e15SLouis Dionne static_assert(
18331191e15SLouis Dionne     std::regular_invocable<lvalue_cv_function_object const volatile&, int*>);
18431191e15SLouis Dionne //
18531191e15SLouis Dionne struct rvalue_function_object {
18631191e15SLouis Dionne   void operator()() &&;
18731191e15SLouis Dionne };
18831191e15SLouis Dionne static_assert(std::regular_invocable<rvalue_function_object>);
18931191e15SLouis Dionne static_assert(!std::regular_invocable<rvalue_function_object const>);
19031191e15SLouis Dionne static_assert(!std::regular_invocable<rvalue_function_object volatile>);
19131191e15SLouis Dionne static_assert(!std::regular_invocable<rvalue_function_object const volatile>);
19231191e15SLouis Dionne static_assert(!std::regular_invocable<rvalue_function_object&>);
19331191e15SLouis Dionne static_assert(!std::regular_invocable<rvalue_function_object const&>);
19431191e15SLouis Dionne static_assert(!std::regular_invocable<rvalue_function_object volatile&>);
19531191e15SLouis Dionne static_assert(!std::regular_invocable<rvalue_function_object const volatile&>);
19631191e15SLouis Dionne 
19731191e15SLouis Dionne struct rvalue_const_function_object {
19831191e15SLouis Dionne   void operator()(int) const&&;
19931191e15SLouis Dionne };
20031191e15SLouis Dionne static_assert(std::regular_invocable<rvalue_const_function_object, int>);
20131191e15SLouis Dionne static_assert(std::regular_invocable<rvalue_const_function_object const, int>);
20231191e15SLouis Dionne static_assert(
20331191e15SLouis Dionne     !std::regular_invocable<rvalue_const_function_object volatile, int>);
20431191e15SLouis Dionne static_assert(
20531191e15SLouis Dionne     !std::regular_invocable<rvalue_const_function_object const volatile, int>);
20631191e15SLouis Dionne static_assert(!std::regular_invocable<rvalue_const_function_object&, int>);
20731191e15SLouis Dionne static_assert(
20831191e15SLouis Dionne     !std::regular_invocable<rvalue_const_function_object const&, int>);
20931191e15SLouis Dionne static_assert(
21031191e15SLouis Dionne     !std::regular_invocable<rvalue_const_function_object volatile&, int>);
21131191e15SLouis Dionne static_assert(
21231191e15SLouis Dionne     !std::regular_invocable<rvalue_const_function_object const volatile&, int>);
21331191e15SLouis Dionne 
21431191e15SLouis Dionne struct rvalue_volatile_function_object {
21531191e15SLouis Dionne   void operator()(int, int) volatile&&;
21631191e15SLouis Dionne };
21731191e15SLouis Dionne static_assert(
21831191e15SLouis Dionne     std::regular_invocable<rvalue_volatile_function_object, int, int>);
21931191e15SLouis Dionne static_assert(
22031191e15SLouis Dionne     !std::regular_invocable<rvalue_volatile_function_object const, int, int>);
22131191e15SLouis Dionne static_assert(
22231191e15SLouis Dionne     std::regular_invocable<rvalue_volatile_function_object volatile, int, int>);
22331191e15SLouis Dionne static_assert(!std::regular_invocable<
22431191e15SLouis Dionne               rvalue_volatile_function_object const volatile, int, int>);
22531191e15SLouis Dionne static_assert(
22631191e15SLouis Dionne     !std::regular_invocable<rvalue_volatile_function_object&, int, int>);
22731191e15SLouis Dionne static_assert(
22831191e15SLouis Dionne     !std::regular_invocable<rvalue_volatile_function_object const&, int, int>);
22931191e15SLouis Dionne static_assert(!std::regular_invocable<rvalue_volatile_function_object volatile&,
23031191e15SLouis Dionne                                       int, int>);
23131191e15SLouis Dionne static_assert(!std::regular_invocable<
23231191e15SLouis Dionne               rvalue_volatile_function_object const volatile&, int, int>);
23331191e15SLouis Dionne 
23431191e15SLouis Dionne struct rvalue_cv_function_object {
23531191e15SLouis Dionne   void operator()(int[]) const volatile&&;
23631191e15SLouis Dionne };
23731191e15SLouis Dionne static_assert(std::regular_invocable<rvalue_cv_function_object, int*>);
23831191e15SLouis Dionne static_assert(std::regular_invocable<rvalue_cv_function_object const, int*>);
23931191e15SLouis Dionne static_assert(std::regular_invocable<rvalue_cv_function_object volatile, int*>);
24031191e15SLouis Dionne static_assert(
24131191e15SLouis Dionne     std::regular_invocable<rvalue_cv_function_object const volatile, int*>);
24231191e15SLouis Dionne static_assert(!std::regular_invocable<rvalue_cv_function_object&, int*>);
24331191e15SLouis Dionne static_assert(!std::regular_invocable<rvalue_cv_function_object const&, int*>);
24431191e15SLouis Dionne static_assert(
24531191e15SLouis Dionne     !std::regular_invocable<rvalue_cv_function_object volatile&, int*>);
24631191e15SLouis Dionne static_assert(
24731191e15SLouis Dionne     !std::regular_invocable<rvalue_cv_function_object const volatile&, int*>);
24831191e15SLouis Dionne 
24931191e15SLouis Dionne struct multiple_overloads {
25031191e15SLouis Dionne   struct A {};
25131191e15SLouis Dionne   struct B { B(int); };
25231191e15SLouis Dionne   struct AB : A, B {};
25331191e15SLouis Dionne   struct O {};
25431191e15SLouis Dionne   void operator()(A) const;
25531191e15SLouis Dionne   void operator()(B) const;
25631191e15SLouis Dionne };
25731191e15SLouis Dionne static_assert(std::regular_invocable<multiple_overloads, multiple_overloads::A>);
25831191e15SLouis Dionne static_assert(std::regular_invocable<multiple_overloads, multiple_overloads::B>);
25931191e15SLouis Dionne static_assert(std::regular_invocable<multiple_overloads, int>);
26031191e15SLouis Dionne static_assert(!std::regular_invocable<multiple_overloads, multiple_overloads::AB>);
26131191e15SLouis Dionne static_assert(!std::regular_invocable<multiple_overloads, multiple_overloads::O>);
26231191e15SLouis Dionne } // namespace function_objects
26331191e15SLouis Dionne 
26431191e15SLouis Dionne namespace pointer_to_member_functions {
26531191e15SLouis Dionne   template<class Member, class T, class... Args>
26688b73a98SLouis Dionne   constexpr bool check_member_is_invocable()
26731191e15SLouis Dionne   {
2685a3c2763SArthur O'Dwyer     constexpr bool result = std::regular_invocable<Member, T&&, Args...>;
26931191e15SLouis Dionne     using uncv_t = std::remove_cvref_t<T>;
27031191e15SLouis Dionne     static_assert(std::regular_invocable<Member, uncv_t*, Args...> == result);
27131191e15SLouis Dionne     static_assert(std::regular_invocable<Member, std::unique_ptr<uncv_t>, Args...> == result);
27231191e15SLouis Dionne     static_assert(std::regular_invocable<Member, std::reference_wrapper<uncv_t>, Args...> == result);
27331191e15SLouis Dionne     static_assert(!std::regular_invocable<Member, std::nullptr_t, Args...>);
27431191e15SLouis Dionne     static_assert(!std::regular_invocable<Member, int, Args...>);
27531191e15SLouis Dionne     static_assert(!std::regular_invocable<Member, int*, Args...>);
27631191e15SLouis Dionne     static_assert(!std::regular_invocable<Member, double*, Args...>);
27731191e15SLouis Dionne     struct S2 {};
27831191e15SLouis Dionne     static_assert(!std::regular_invocable<Member, S2*, Args...>);
27931191e15SLouis Dionne     return result;
28031191e15SLouis Dionne   }
28131191e15SLouis Dionne 
28231191e15SLouis Dionne static_assert(check_member_is_invocable<int S::*, S>());
28331191e15SLouis Dionne static_assert(std::regular_invocable<int S::*, S&>);
28431191e15SLouis Dionne static_assert(std::regular_invocable<int S::*, S const&>);
28531191e15SLouis Dionne static_assert(std::regular_invocable<int S::*, S volatile&>);
28631191e15SLouis Dionne static_assert(std::regular_invocable<int S::*, S const volatile&>);
28731191e15SLouis Dionne static_assert(std::regular_invocable<int S::*, S&&>);
28831191e15SLouis Dionne static_assert(std::regular_invocable<int S::*, S const&&>);
28931191e15SLouis Dionne static_assert(std::regular_invocable<int S::*, S volatile&&>);
29031191e15SLouis Dionne static_assert(std::regular_invocable<int S::*, S const volatile&&>);
29131191e15SLouis Dionne 
29231191e15SLouis Dionne static_assert(check_member_is_invocable<int (S::*)(int), S, int>());
29331191e15SLouis Dionne static_assert(!check_member_is_invocable<int (S::*)(int), S>());
29431191e15SLouis Dionne using unqualified = void (S::*)();
29531191e15SLouis Dionne static_assert(std::regular_invocable<unqualified, S&>);
29631191e15SLouis Dionne static_assert(!std::regular_invocable<unqualified, S const&>);
29731191e15SLouis Dionne static_assert(!std::regular_invocable<unqualified, S volatile&>);
29831191e15SLouis Dionne static_assert(!std::regular_invocable<unqualified, S const volatile&>);
29931191e15SLouis Dionne static_assert(std::regular_invocable<unqualified, S&&>);
30031191e15SLouis Dionne static_assert(!std::regular_invocable<unqualified, S const&&>);
30131191e15SLouis Dionne static_assert(!std::regular_invocable<unqualified, S volatile&&>);
30231191e15SLouis Dionne static_assert(!std::regular_invocable<unqualified, S const volatile&&>);
30331191e15SLouis Dionne 
30431191e15SLouis Dionne static_assert(check_member_is_invocable<int (S::*)(double) const, S, double>());
30531191e15SLouis Dionne using const_qualified = void (S::*)() const;
30631191e15SLouis Dionne static_assert(std::regular_invocable<const_qualified, S&>);
30731191e15SLouis Dionne static_assert(std::regular_invocable<const_qualified, S const&>);
30831191e15SLouis Dionne static_assert(!std::regular_invocable<const_qualified, S volatile&>);
30931191e15SLouis Dionne static_assert(!std::regular_invocable<const_qualified, S const volatile&>);
31031191e15SLouis Dionne static_assert(std::regular_invocable<const_qualified, S&&>);
31131191e15SLouis Dionne static_assert(std::regular_invocable<const_qualified, S const&&>);
31231191e15SLouis Dionne static_assert(!std::regular_invocable<const_qualified, S volatile&&>);
31331191e15SLouis Dionne static_assert(!std::regular_invocable<const_qualified, S const volatile&&>);
31431191e15SLouis Dionne 
31531191e15SLouis Dionne static_assert(
31631191e15SLouis Dionne     check_member_is_invocable<int (S::*)(double[]) volatile, S, double*>());
31731191e15SLouis Dionne using volatile_qualified = void (S::*)() volatile;
31831191e15SLouis Dionne static_assert(std::regular_invocable<volatile_qualified, S&>);
31931191e15SLouis Dionne static_assert(!std::regular_invocable<volatile_qualified, S const&>);
32031191e15SLouis Dionne static_assert(std::regular_invocable<volatile_qualified, S volatile&>);
32131191e15SLouis Dionne static_assert(!std::regular_invocable<volatile_qualified, S const volatile&>);
32231191e15SLouis Dionne static_assert(std::regular_invocable<volatile_qualified, S&&>);
32331191e15SLouis Dionne static_assert(!std::regular_invocable<volatile_qualified, S const&&>);
32431191e15SLouis Dionne static_assert(std::regular_invocable<volatile_qualified, S volatile&&>);
32531191e15SLouis Dionne static_assert(!std::regular_invocable<volatile_qualified, S const volatile&&>);
32631191e15SLouis Dionne 
32731191e15SLouis Dionne static_assert(check_member_is_invocable<int (S::*)(int, S&) const volatile, S,
32831191e15SLouis Dionne                                         int, S&>());
32931191e15SLouis Dionne using cv_qualified = void (S::*)() const volatile;
33031191e15SLouis Dionne static_assert(std::regular_invocable<cv_qualified, S&>);
33131191e15SLouis Dionne static_assert(std::regular_invocable<cv_qualified, S const&>);
33231191e15SLouis Dionne static_assert(std::regular_invocable<cv_qualified, S volatile&>);
33331191e15SLouis Dionne static_assert(std::regular_invocable<cv_qualified, S const volatile&>);
33431191e15SLouis Dionne static_assert(std::regular_invocable<cv_qualified, S&&>);
33531191e15SLouis Dionne static_assert(std::regular_invocable<cv_qualified, S const&&>);
33631191e15SLouis Dionne static_assert(std::regular_invocable<cv_qualified, S volatile&&>);
33731191e15SLouis Dionne static_assert(std::regular_invocable<cv_qualified, S const volatile&&>);
33831191e15SLouis Dionne 
33931191e15SLouis Dionne static_assert(check_member_is_invocable<int (S::*)() &, S&>());
34031191e15SLouis Dionne using lvalue_qualified = void (S::*)() &;
34131191e15SLouis Dionne static_assert(std::regular_invocable<lvalue_qualified, S&>);
34231191e15SLouis Dionne static_assert(!std::regular_invocable<lvalue_qualified, S const&>);
34331191e15SLouis Dionne static_assert(!std::regular_invocable<lvalue_qualified, S volatile&>);
34431191e15SLouis Dionne static_assert(!std::regular_invocable<lvalue_qualified, S const volatile&>);
34531191e15SLouis Dionne static_assert(!std::regular_invocable<lvalue_qualified, S&&>);
34631191e15SLouis Dionne static_assert(!std::regular_invocable<lvalue_qualified, S const&&>);
34731191e15SLouis Dionne static_assert(!std::regular_invocable<lvalue_qualified, S volatile&&>);
34831191e15SLouis Dionne static_assert(!std::regular_invocable<lvalue_qualified, S const volatile&&>);
34931191e15SLouis Dionne 
35031191e15SLouis Dionne static_assert(check_member_is_invocable<int (S::*)() const&, S>());
35131191e15SLouis Dionne using lvalue_const_qualified = void (S::*)() const&;
35231191e15SLouis Dionne static_assert(std::regular_invocable<lvalue_const_qualified, S&>);
35331191e15SLouis Dionne static_assert(std::regular_invocable<lvalue_const_qualified, S const&>);
35431191e15SLouis Dionne static_assert(!std::regular_invocable<lvalue_const_qualified, S volatile&>);
35531191e15SLouis Dionne static_assert(
35631191e15SLouis Dionne     !std::regular_invocable<lvalue_const_qualified, S const volatile&>);
35731191e15SLouis Dionne static_assert(std::regular_invocable<lvalue_const_qualified, S&&>);
35831191e15SLouis Dionne static_assert(std::regular_invocable<lvalue_const_qualified, S const&&>);
35931191e15SLouis Dionne static_assert(!std::regular_invocable<lvalue_const_qualified, S volatile&&>);
36031191e15SLouis Dionne static_assert(
36131191e15SLouis Dionne     !std::regular_invocable<lvalue_const_qualified, S const volatile&&>);
36231191e15SLouis Dionne 
36331191e15SLouis Dionne static_assert(check_member_is_invocable<int (S::*)() volatile&, S&>());
36431191e15SLouis Dionne using lvalue_volatile_qualified = void (S::*)() volatile&;
36531191e15SLouis Dionne static_assert(std::regular_invocable<lvalue_volatile_qualified, S&>);
36631191e15SLouis Dionne static_assert(!std::regular_invocable<lvalue_volatile_qualified, S const&>);
36731191e15SLouis Dionne static_assert(std::regular_invocable<lvalue_volatile_qualified, S volatile&>);
36831191e15SLouis Dionne static_assert(
36931191e15SLouis Dionne     !std::regular_invocable<lvalue_volatile_qualified, S const volatile&>);
37031191e15SLouis Dionne static_assert(!std::regular_invocable<lvalue_volatile_qualified, S&&>);
37131191e15SLouis Dionne static_assert(!std::regular_invocable<lvalue_volatile_qualified, S const&&>);
37231191e15SLouis Dionne static_assert(!std::regular_invocable<lvalue_volatile_qualified, S volatile&&>);
37331191e15SLouis Dionne static_assert(
37431191e15SLouis Dionne     !std::regular_invocable<lvalue_volatile_qualified, S const volatile&&>);
37531191e15SLouis Dionne 
37631191e15SLouis Dionne static_assert(check_member_is_invocable<int (S::*)() const volatile&, S&>());
37731191e15SLouis Dionne using lvalue_cv_qualified = void (S::*)() const volatile&;
37831191e15SLouis Dionne static_assert(std::regular_invocable<lvalue_cv_qualified, S&>);
37931191e15SLouis Dionne static_assert(std::regular_invocable<lvalue_cv_qualified, S const&>);
38031191e15SLouis Dionne static_assert(std::regular_invocable<lvalue_cv_qualified, S volatile&>);
38131191e15SLouis Dionne static_assert(std::regular_invocable<lvalue_cv_qualified, S const volatile&>);
38231191e15SLouis Dionne static_assert(!std::regular_invocable<lvalue_cv_qualified, S&&>);
38331191e15SLouis Dionne static_assert(!std::regular_invocable<lvalue_cv_qualified, S const&&>);
38431191e15SLouis Dionne static_assert(!std::regular_invocable<lvalue_cv_qualified, S volatile&&>);
38531191e15SLouis Dionne static_assert(!std::regular_invocable<lvalue_cv_qualified, S const volatile&&>);
38631191e15SLouis Dionne 
38731191e15SLouis Dionne using rvalue_unqualified = void (S::*)() &&;
38831191e15SLouis Dionne static_assert(!std::regular_invocable<rvalue_unqualified, S&>);
38931191e15SLouis Dionne static_assert(!std::regular_invocable<rvalue_unqualified, S const&>);
39031191e15SLouis Dionne static_assert(!std::regular_invocable<rvalue_unqualified, S volatile&>);
39131191e15SLouis Dionne static_assert(!std::regular_invocable<rvalue_unqualified, S const volatile&>);
39231191e15SLouis Dionne static_assert(std::regular_invocable<rvalue_unqualified, S&&>);
39331191e15SLouis Dionne static_assert(!std::regular_invocable<rvalue_unqualified, S const&&>);
39431191e15SLouis Dionne static_assert(!std::regular_invocable<rvalue_unqualified, S volatile&&>);
39531191e15SLouis Dionne static_assert(!std::regular_invocable<rvalue_unqualified, S const volatile&&>);
39631191e15SLouis Dionne 
39731191e15SLouis Dionne using rvalue_const_unqualified = void (S::*)() const&&;
39831191e15SLouis Dionne static_assert(!std::regular_invocable<rvalue_const_unqualified, S&>);
39931191e15SLouis Dionne static_assert(!std::regular_invocable<rvalue_const_unqualified, S const&>);
40031191e15SLouis Dionne static_assert(!std::regular_invocable<rvalue_const_unqualified, S volatile&>);
40131191e15SLouis Dionne static_assert(
40231191e15SLouis Dionne     !std::regular_invocable<rvalue_const_unqualified, S const volatile&>);
40331191e15SLouis Dionne static_assert(std::regular_invocable<rvalue_const_unqualified, S&&>);
40431191e15SLouis Dionne static_assert(std::regular_invocable<rvalue_const_unqualified, S const&&>);
40531191e15SLouis Dionne static_assert(!std::regular_invocable<rvalue_const_unqualified, S volatile&&>);
40631191e15SLouis Dionne static_assert(
40731191e15SLouis Dionne     !std::regular_invocable<rvalue_const_unqualified, S const volatile&&>);
40831191e15SLouis Dionne 
40931191e15SLouis Dionne using rvalue_volatile_unqualified = void (S::*)() volatile&&;
41031191e15SLouis Dionne static_assert(!std::regular_invocable<rvalue_volatile_unqualified, S&>);
41131191e15SLouis Dionne static_assert(!std::regular_invocable<rvalue_volatile_unqualified, S const&>);
41231191e15SLouis Dionne static_assert(
41331191e15SLouis Dionne     !std::regular_invocable<rvalue_volatile_unqualified, S volatile&>);
41431191e15SLouis Dionne static_assert(
41531191e15SLouis Dionne     !std::regular_invocable<rvalue_volatile_unqualified, S const volatile&>);
41631191e15SLouis Dionne static_assert(std::regular_invocable<rvalue_volatile_unqualified, S&&>);
41731191e15SLouis Dionne static_assert(!std::regular_invocable<rvalue_volatile_unqualified, S const&&>);
41831191e15SLouis Dionne static_assert(
41931191e15SLouis Dionne     std::regular_invocable<rvalue_volatile_unqualified, S volatile&&>);
42031191e15SLouis Dionne static_assert(
42131191e15SLouis Dionne     !std::regular_invocable<rvalue_volatile_unqualified, S const volatile&&>);
42231191e15SLouis Dionne 
42331191e15SLouis Dionne using rvalue_cv_unqualified = void (S::*)() const volatile&&;
42431191e15SLouis Dionne static_assert(!std::regular_invocable<rvalue_cv_unqualified, S&>);
42531191e15SLouis Dionne static_assert(!std::regular_invocable<rvalue_cv_unqualified, S const&>);
42631191e15SLouis Dionne static_assert(!std::regular_invocable<rvalue_cv_unqualified, S volatile&>);
42731191e15SLouis Dionne static_assert(
42831191e15SLouis Dionne     !std::regular_invocable<rvalue_cv_unqualified, S const volatile&>);
42931191e15SLouis Dionne static_assert(std::regular_invocable<rvalue_cv_unqualified, S&&>);
43031191e15SLouis Dionne static_assert(std::regular_invocable<rvalue_cv_unqualified, S const&&>);
43131191e15SLouis Dionne static_assert(std::regular_invocable<rvalue_cv_unqualified, S volatile&&>);
43231191e15SLouis Dionne static_assert(
43331191e15SLouis Dionne     std::regular_invocable<rvalue_cv_unqualified, S const volatile&&>);
43431191e15SLouis Dionne } // namespace pointer_to_member_functions
43531191e15SLouis Dionne 
43631191e15SLouis Dionne // Check the concept with closure types (and also check for subsumption)
43731191e15SLouis Dionne template<class F, class... Args>
43831191e15SLouis Dionne constexpr bool is_regular_invocable(F, Args&&...) {
43931191e15SLouis Dionne   return false;
44031191e15SLouis Dionne }
44131191e15SLouis Dionne 
44231191e15SLouis Dionne template<class F, class... Args>
44331191e15SLouis Dionne requires std::invocable<F, Args...>
44431191e15SLouis Dionne constexpr bool is_regular_invocable(F, Args&&...) {
44531191e15SLouis Dionne   return false;
44631191e15SLouis Dionne }
44731191e15SLouis Dionne 
44831191e15SLouis Dionne template<class F, class... Args>
44931191e15SLouis Dionne requires std::regular_invocable<F, Args...> && true
45031191e15SLouis Dionne constexpr bool is_regular_invocable(F, Args&&...) {
45131191e15SLouis Dionne   return true;
45231191e15SLouis Dionne }
45331191e15SLouis Dionne 
45431191e15SLouis Dionne static_assert(is_regular_invocable([] {}));
45531191e15SLouis Dionne static_assert(is_regular_invocable([](int) {}, 0));
45631191e15SLouis Dionne static_assert(is_regular_invocable([](int) {}, 0L));
45731191e15SLouis Dionne static_assert(!is_regular_invocable([](int) {}, nullptr));
45831191e15SLouis Dionne 
45931191e15SLouis Dionne int i = 0;
46031191e15SLouis Dionne static_assert(is_regular_invocable([](int&) {}, i));
461