summaryrefslogtreecommitdiff
path: root/src/core/templates.h
blob: 9b4bcac3a58d74a7d1e699d35709451bcb86e619 (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
#pragma once

namespace saw {

template <class T, class... TL> struct parameter_pack_index;

template <class T, class... TL> struct parameter_pack_index<T, T, TL...> {
	static constexpr size_t value = 0u;
};

template <class T, class TL0, class... TL>
struct parameter_pack_index<T, TL0, TL...> {
	static constexpr size_t value =
		1u + parameter_pack_index<T, TL...>::value;
};

template <size_t N, class... T> struct parameter_pack_type;

template <class TN, class... T> struct parameter_pack_type<0, TN, T...> {
	using type = TN;
};

template <size_t N, class TN, class... T>
struct parameter_pack_type<N, TN, T...> {
	static_assert(sizeof...(T) > 0, "Exhausted parameters");
	using type = typename parameter_pack_type<N - 1, T...>::type;
};
/*
 * Nightmare inducing compiler problems found here. Somehow non-type
 * string_literals cannot be resolved as non-type primitive template values can.
 * This is the workaround
 */
template <string_literal V, string_literal Key0, string_literal... Keys>
struct parameter_key_pack_index_helper {
	static constexpr size_t value =
		(V == Key0)
			? (0u)
			: (1u + parameter_key_pack_index_helper<V, Keys...>::value);
};

template <string_literal V, string_literal Key0>
struct parameter_key_pack_index_helper<V, Key0> {
	static constexpr size_t value = (V == Key0) ? (0u) : (1u);
};

template <string_literal V, string_literal... Keys>
struct parameter_key_pack_index {
	static constexpr size_t value =
		parameter_key_pack_index_helper<V, Keys...>::value;
	static_assert(value < sizeof...(Keys),
				  "Provided string_literal doesn't exist in searched list");
};

}