1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
#pragma once
#include "asl/base/meta.hpp"
#include "asl/base/utility.hpp"
namespace asl {
template<typename... Args, typename C>
constexpr auto invoke(is_func auto C::* f, auto&& self, Args&&... args)
-> decltype((self.*f)(ASL_FWD(args)...))
requires requires {
(self.*f)(ASL_FWD(args)...);
}
{
return (ASL_FWD(self).*f)(ASL_FWD(args)...);
}
template<typename... Args, typename C>
constexpr auto invoke(is_func auto C::* f, auto* self, Args&&... args)
-> decltype((self->*f)(ASL_FWD(args)...))
requires requires {
(self->*f)(ASL_FWD(args)...);
}
{
return (self->*f)(ASL_FWD(args)...);
}
template<typename... Args, typename C>
constexpr auto invoke(is_object auto C::* m, auto&& self, Args&&...)
-> decltype(self.*m)
requires (
sizeof...(Args) == 0 &&
requires { self.*m; }
)
{
return ASL_FWD(self).*m;
}
template<typename... Args, typename C>
constexpr auto invoke(is_object auto C::* m, auto* self, Args&&...)
-> decltype(self->*m)
requires (
sizeof...(Args) == 0 &&
requires { self->*m; }
)
{
return self->*m;
}
template<typename... Args>
constexpr auto invoke(auto&& f, Args&&... args)
-> decltype(f(ASL_FWD(args)...))
requires requires {
f(ASL_FWD(args)...);
}
{
return ASL_FWD(f)(ASL_FWD(args)...);
}
template<typename Void, typename F, typename... Args>
struct _invoke_result_helper;
template<typename R, typename... Args>
struct _invoke_result_helper<void, R, Args...>
{
using type = decltype(invoke(declval<R>(), declval<Args>()...));
};
template<typename F, typename... Args>
using invoke_result_t = _invoke_result_helper<void, F, Args...>::type;
template<typename F, typename... Args>
concept invocable = requires (F&& f, Args&&... args)
{
invoke(ASL_FWD(f), ASL_FWD(args)...);
};
} // namespace asl
|