-
Notifications
You must be signed in to change notification settings - Fork 0
/
Function.hpp
70 lines (70 loc) · 2.41 KB
/
Function.hpp
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
#pragma once
#include "Any.hpp"
namespace CTC {
namespace details {
template <typename T>
struct GetFunctionType;
template <typename RetType, typename ObjType, typename... ArgsType>
struct GetFunctionType<RetType (ObjType::*)(ArgsType...) const> {
using type = RetType(ArgsType...);
};
template <typename RetType, typename ObjType, typename... ArgsType>
struct GetFunctionType<RetType (ObjType::*)(ArgsType...) volatile> {
using type = RetType(ArgsType...);
};
template <typename RetType, typename ObjType, typename... ArgsType>
struct GetFunctionType<RetType (ObjType::*)(ArgsType...) const volatile> {
using type = RetType(ArgsType...);
};
template <typename RetType, typename ObjType, typename... ArgsType>
struct GetFunctionType<RetType (ObjType::*)(ArgsType...)> {
using type = RetType(ArgsType...);
};
template <typename RetType, typename ObjType>
struct GetFunctionType<RetType (ObjType::*)() const> {
using type = RetType();
};
template <typename RetType, typename ObjType>
struct GetFunctionType<RetType (ObjType::*)() volatile> {
using type = RetType();
};
template <typename RetType, typename ObjType>
struct GetFunctionType<RetType (ObjType::*)() const volatile> {
using type = RetType();
};
template <typename RetType, typename ObjType>
struct GetFunctionType<RetType (ObjType::*)()> {
using type = RetType();
};
} // namespace details
template <typename T>
struct Function;
template <typename RetType, typename... ArgsType>
struct Function<RetType(ArgsType...)> {
Any fn;
RetType (*call)(Any&, ArgsType...);
template <typename T>
Function(T f) : fn(f) {
call = [](Any& fn, ArgsType... args) { return (fn.cast_to_ref<T>())(args...); };
}
auto operator()(ArgsType&&... args) { return call(fn, args...); }
Function(std::nullptr_t) : fn(nullptr) {}
};
template <typename RetType>
struct Function<RetType()> {
Any fn;
RetType (*call)(Any&);
template <typename T>
Function(T f) : fn(f) {
call = [](Any& fn) { return (fn.cast_to_ref<T>())(); };
}
auto operator()() { return call(fn); }
Function(std::nullptr_t) : fn(nullptr) {}
};
template <typename T>
Function(T) -> Function<typename details::GetFunctionType<decltype(&T::operator())>::type>;
template <typename RetType, typename... ArgsType>
Function(RetType (*)(ArgsType...)) -> Function<RetType(ArgsType...)>;
template <typename RetType>
Function(RetType (*)()) -> Function<RetType()>;
} // namespace CTC