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
79
80
81
82
83
84
85
86
87
88
89
|
#pragma once
#include "string_literal.h"
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 {
static_assert(always_false<T...>, "Should've been caught by the specializations");
};
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");
static_assert(N > 0, "Invalid number. Should've been caught");
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");
};
template <size_t i, size_t s, string_literal Key0, string_literal... Keys>
struct parameter_key_pack_type_helper {
static constexpr string_literal literal = parameter_key_pack_type_helper<i, s+1, Keys...>::literal;
};
template <size_t i, string_literal Key0, string_literal... Keys>
struct parameter_key_pack_type_helper<i, i, Key0, Keys...> {
static constexpr string_literal literal = Key0;
};
template <size_t i, string_literal... Keys>
struct parameter_key_pack_type {
static constexpr string_literal literal = parameter_key_pack_type_helper<i, 0, Keys...>::literal;
static_assert(i < sizeof...(Keys), "Provided index is too large in list");
};
template<typename T, T... V>
struct ct_multiply;
template<typename T>
struct ct_multiply<T> {
static constexpr T value = 1;
};
template<typename T, T V0, T... VN>
struct ct_multiply<T, V0, VN...> {
static constexpr T value = V0 * templ_multiply<T,VN...>::value;
};
}
|