aboutsummaryrefslogtreecommitdiff
path: root/src/util/function.tpp
blob: 6ff939b7ae447daa2389a1047d7e60210ca48acf (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
66
67
68
69
70
71
72
73
74
75
#pragma once

#include "function.hpp"

#include <utility>

template <typename>
struct remove_cv_seq;

template <typename Return, typename... Args>
struct remove_cv_seq<Return(Args...)>
{
	using type = Return(Args...);
};

template <typename Return, typename... Args>
struct remove_cv_seq<Return(Args...) const>
{
	using type = Return(Args...);
};

template <typename Return, typename... Args>
struct remove_cv_seq<Return(Args...) &>
{
	using type = Return(Args...);
};

template <typename Function>
constexpr inline auto extract_signature(Function * /*unused*/) noexcept
{
	return Signature<typename remove_cv_seq<Function>::type>();
}

template <typename Class, typename Function>
constexpr inline auto extract_signature(Function Class::* /*unused*/) noexcept
{
	return Signature<typename remove_cv_seq<Function>::type>();
}

template <typename Function>
constexpr inline auto extract_signature(Function const & /*unused*/) noexcept
	-> decltype(&Function::operator(), extract_signature(&Function::operator()))
{
	return extract_signature(&Function::operator());
}

template <typename Function, typename Return, typename... Args>
inline auto get_normalized_lambda(Function &&func,
								  Signature<Return(Args...)> /*unused*/) noexcept
{
	// Static copy of func. This will make it accessible for the lambda without using a
	// lamda capture
	static auto static_func = Function(std::forward<Function>(func));

	return +[](Args... args) noexcept(
				noexcept(std::declval<Function>()(std::forward<Args>(args)...))) -> Return
	{
		return static_func(std::forward<Args>(args)...);
	};
}

/**
 * Normalizes the type signature of a lambda function.
 *
 * This will make a lambda with captures passable to other functions.
 *
 * @param func A lambda function
 * @returns The lambda function normalized.
 */
template <typename Function>
constexpr auto normalize_lambda(Function &&func) noexcept
{
	return get_normalized_lambda(std::forward<Function>(func),
								 extract_signature(std::forward<Function>(func)));
}