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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
#pragma once
/*
Motivation: consider you have a template class with many parameters
with default associations
template <typename A = TDefA,
typename B = TDefB,
typename C = TDefC,
typename D = TDefD>
class TExample {
};
consider you would like to provide easy to use interface to tune all
these parameters in position independed manner,
In that case TTune would be helpful for you.
How to use:
First step: declare a struct with all default associations
struct TDefaultTune {
using TStructA = TDefA;
using TStructB = TDefB;
using TStructC = TDefC;
using TStructD = TDefD;
};
Second step: declare helper names visible to a user
DeclareTuneTypeParam(TTuneParamA, TStructA);
DeclareTuneTypeParam(TTuneParamB, TStructB);
DeclareTuneTypeParam(TTuneParamC, TStructC);
DeclareTuneTypeParam(TTuneParamD, TStructD);
Third step: declare TExample this way:
template <typename...TParams>
class TExample {
using TMyParams = TTune<TDefaultTune, TParams...>;
using TActualA = TMyParams::TStructA;
using TActualB = TMyParams::TStructB;
...
};
TTune<TDefaultTune, TParams...> is a struct with the default parameteres
taken from TDefaultTune and overridden from "TParams...".
for example: "TTune<TDefaultTune, TTuneParamC<TUserClass>>"
will be virtually the same as:
struct TTunedClass {
using TStructA = TDefA;
using TStructB = TDefB;
using TStructC = TUserClass;
using TStructD = TDefD;
};
From now on you can tune your TExample in the following manner:
using TCustomClass =
TExample <TTuneParamA<TUserStruct1>, TTuneParamD<TUserStruct2>>;
You can also tweak constant expressions in your TDefaultTune.
Consider you have:
struct TDefaultTune {
static constexpr ui32 MySize = 42;
};
declare an interface to modify the parameter this way:
DeclareTuneValueParam(TStructSize, ui32, MySize);
and tweak your class:
using TTwiceBigger = TExample<TStructSize<84>>;
*/
#define DeclareTuneTypeParam(TParamName, InternalName) \
template <typename TNewType> \
struct TParamName { \
template <typename TBase> \
struct TApply: public TBase { \
using InternalName = TNewType; \
}; \
}
#define DeclareTuneValueParam(TParamName, TValueType, InternalName) \
template <TValueType NewValue> \
struct TParamName { \
template <typename TBase> \
struct TApply: public TBase { \
static constexpr TValueType InternalName = NewValue; \
}; \
}
#define DeclareTuneContainer(TParamName, InternalName) \
template <template <typename, typename...> class TNewContainer> \
struct TParamName { \
template <typename TBase> \
struct TApply: public TBase { \
template <typename TElem, typename... TRest> \
using InternalName = TNewContainer<TElem, TRest...>; \
}; \
}
namespace NTunePrivate {
template <typename TBase, typename... TParams>
struct TFold;
template <typename TBase>
struct TFold<TBase>: public TBase {
};
template <typename TBase, typename TFirstArg, typename... TRest>
struct TFold<TBase, TFirstArg, TRest...>
: public TFold<typename TFirstArg::template TApply<TBase>, TRest...> {
};
}
template <typename TDefault, typename... TParams>
struct TTune: public NTunePrivate::TFold<TDefault, TParams...> {
};
|