summaryrefslogtreecommitdiff
path: root/asl/functional.hpp
blob: 967a2a293da76f6716279e1ab63bfda5f86c7dca (plain)
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
#pragma once

#include "asl/meta.hpp"
#include "asl/utility.hpp"

namespace asl {

template<typename... Args, typename C>
constexpr auto invoke(is_func auto C::* f, auto&& self, Args&&... 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)
    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&&...)
    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&&...)
    requires (
        sizeof...(Args) == 0 &&
        requires { self->*m; }
    )
{
    return self->*m;
}

template<typename... Args>
constexpr auto invoke(auto&& f, Args&&... args)
    requires requires {
        f(ASL_FWD(args)...);
    }
{
    return ASL_FWD(f)(ASL_FWD(args)...);
}

template<typename F> struct _result_of_helper;

template<typename R, typename... Args>
struct _result_of_helper<R(Args...)>
{
    using type = decltype(invoke(declval<R>(), declval<Args>()...));
};

template<typename F> using result_of_t = _result_of_helper<F>::type;

} // namespace asl