Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
OptionalArgs.hxx
Go to the documentation of this file.
1
36#ifndef _UTILS_OPTIONALARGS_HXX_
37#define _UTILS_OPTIONALARGS_HXX_
38
41template <typename DATA_TYPE, int N> class Fetcher
42{
43public:
44 constexpr Fetcher()
45 {
46 }
47};
48
51template <typename DATA_TYPE, int N, DATA_TYPE defval> class Specifier
52{
53public:
56 constexpr Specifier(const DATA_TYPE d)
57 : d_(d)
58 {
59 }
60
64 typedef DATA_TYPE data_type;
66 static constexpr DATA_TYPE default_value()
67 {
68 return defval;
69 }
71 DATA_TYPE d_;
72};
73
86#define DECLARE_OPTIONALARG(SpecName, function_name, DataType, N, DEF) \
87 using SpecName = Specifier<DataType, N, (DEF)>; \
88 using SpecName##Get = Fetcher<DataType, N>; \
89 static constexpr int check_arguments_are_valid(const SpecName s) \
90 { \
91 return 0; \
92 }
93
100#define DEFINE_OPTIONALARG(SpecName, function_name, DataType) \
101 constexpr DataType function_name() const \
102 { \
103 return get(SpecName##Get()); \
104 } \
105 constexpr bool has_##function_name() const \
106 { \
107 return has(SpecName##Get()); \
108 }
109
111template <class Decl, typename... Args> class OptionalArg;
112
122template <class Decl> class OptionalArg<Decl> : public Decl
123{
124public:
126 template <typename... Args>
127 constexpr OptionalArg(Args... args)
128 : check_(check_all_args(args...))
129 {
130 }
131
134 template <class FF> constexpr FF get(const FF f) const
135 {
136 return tried_to_get_unknown_argument() ? f : FF();
137 }
138
141 template <class FF> constexpr bool has(const FF f) const
142 {
143 return tried_to_get_unknown_argument();
144 }
145
146private:
147 using Decl::check_arguments_are_valid;
149 static constexpr int check_arguments_are_valid(const OptionalArg &a)
150 {
151 return 0;
152 }
153
155 template <typename A, typename... Args>
156 static constexpr int check_all_args(const A a, Args... args)
157 {
158 return check_arguments_are_valid(a) + check_all_args(args...);
159 }
160
162 static constexpr int check_all_args()
163 {
164 return 0;
165 }
166
169
172 const int check_;
173};
174
186template <typename Decl, typename Specifier, typename... TArgs>
187class OptionalArg<Decl, Specifier, TArgs...>
188 : public OptionalArg<Decl, TArgs...>
189{
190public:
199 using Base = OptionalArg<Decl, TArgs...>;
200
202 template <typename... Args>
203 constexpr OptionalArg(Args... args)
204 : Base(args...)
205 , d_(GetFromArgs(args...))
206 , has_(HasFromArgs(args...))
207 {
208 }
209
211 constexpr OptionalArg()
212 : d_(GetFromArgs())
213 , has_(false)
214 {
215 }
216
218 constexpr data_type get(const fetcher_type) const
219 {
220 return d_;
221 }
222
224 constexpr bool has(const fetcher_type) const
225 {
226 return has_;
227 }
228
231 using Base::get;
232 using Base::has;
233
234private:
236 template <typename... Args>
237 static constexpr data_type GetFromArgs(
238 const specifier_type spec, Args... args)
239 {
240 return spec.d_;
241 }
242
245 template <typename... Args>
246 static constexpr bool HasFromArgs(const specifier_type spec, Args... args)
247 {
248 return true;
249 }
250
254 template <typename U, typename... Args>
255 static constexpr typename std::enable_if<
256 std::is_convertible<typename std::add_lvalue_reference<U>::type,
257 typename std::add_lvalue_reference<Base>::type>::value,
258 data_type>::type
259 GetFromArgs(const U me, Args... args)
260 {
261 return me.get(fetcher_type());
262 }
265 template <typename U, typename... Args>
266 static constexpr typename std::enable_if<
267 std::is_convertible<typename std::add_lvalue_reference<U>::type,
268 typename std::add_lvalue_reference<Base>::type>::value,
269 bool>::type
270 HasFromArgs(const U me, Args... args)
271 {
272 return me.has(fetcher_type());
273 }
274
280 template <typename T, typename... Args>
281 static constexpr typename std::enable_if<
282 !std::is_convertible<typename std::add_lvalue_reference<T>::type,
283 typename std::add_lvalue_reference<Base>::type>::value,
284 data_type>::type
285 GetFromArgs(const T t, Args... args)
286 {
287 return GetFromArgs(args...);
288 }
293 template <typename T, typename... Args>
294 static constexpr typename std::enable_if<
295 !std::is_convertible<typename std::add_lvalue_reference<T>::type,
296 typename std::add_lvalue_reference<Base>::type>::value,
297 bool>::type
298 HasFromArgs(const T t, Args... args)
299 {
300 return HasFromArgs(args...);
301 }
302
304 static constexpr data_type GetFromArgs()
305 {
306 return specifier_type::default_value();
307 }
309 static constexpr bool HasFromArgs()
310 {
311 return false;
312 }
313
317 bool has_;
318};
319
320#endif // _UTILS_OPTIONALARGS_HXX_
Used as an argument to the get(Fetcher) function in the OptionalArg implementation to select which en...
constexpr OptionalArg()
Constructor ending the recursion.
static constexpr data_type GetFromArgs(const specifier_type spec, Args... args)
This template gets instantiated when the first argument is for us.
constexpr OptionalArg(Args... args)
Constructor.
static constexpr data_type GetFromArgs()
If we've run out of all arguments, we take the default value.
bool has_
Whether the user has specified the value or not.
static constexpr std::enable_if<!std::is_convertible< typenamestd::add_lvalue_reference< T >::type, typenamestd::add_lvalue_reference< Base >::type >::value, bool >::type HasFromArgs(const T t, Args... args)
This template gets instantiated only if the argument is not an OptionalArg (hence not called from the...
Specifier::FetcherType fetcher_type
This is the type we use internally to tag and fetch the value.
Specifier specifier_type
This is the type used by the customer to set the value in the initializer list.
static constexpr std::enable_if< std::is_convertible< typenamestd::add_lvalue_reference< U >::type, typenamestd::add_lvalue_reference< Base >::type >::value, data_type >::type GetFromArgs(const U me, Args... args)
This template gets instantiated for a copy constructor: when the argument is already an OptionalArg (...
static constexpr std::enable_if<!std::is_convertible< typenamestd::add_lvalue_reference< T >::type, typenamestd::add_lvalue_reference< Base >::type >::value, data_type >::type GetFromArgs(const T t, Args... args)
This template gets instantiated only if the argument is not an OptionalArg (hence not called from the...
Specifier::data_type data_type
The type of the actually stored data. Should be POD.
constexpr data_type get(const fetcher_type) const
data_type d_
Data that the user specified (or the default).
static constexpr bool HasFromArgs(const specifier_type spec, Args... args)
Decides whether we have the current argument (from the original list or arguments).
constexpr bool has(const fetcher_type) const
static constexpr std::enable_if< std::is_convertible< typenamestd::add_lvalue_reference< U >::type, typenamestd::add_lvalue_reference< Base >::type >::value, bool >::type HasFromArgs(const U me, Args... args)
This template gets instantiated for a copy constructor: when the argument is already an OptionalArg (...
static constexpr bool HasFromArgs()
If we've run out of all arguments, there is no specifier.
static constexpr int check_all_args(const A a, Args... args)
Beginning of recursion..
static bool tried_to_get_unknown_argument()
unimplemented, causes a link error. Do not ever implement it.
static constexpr int check_arguments_are_valid(const OptionalArg &a)
End of recursion with no leftover arguments.
constexpr FF get(const FF f) const
End of template recursion.
const int check_
This is here only to force computing the check_all_args at compile time (constexpr!...
constexpr OptionalArg(Args... args)
Constructor.
constexpr bool has(const FF f) const
End of template recursion.
static constexpr int check_all_args()
End of recursion.
Declares that a recursive class template is coming.
Used as an argument to the constructor of the OptionalArg implementation to represent that a specific...
static constexpr DATA_TYPE default_value()
Default value when the customer does not specify it.
DATA_TYPE d_
Shuttled argument value.
DATA_TYPE data_type
Type of data held internally.
constexpr Specifier(const DATA_TYPE d)
Constructor.
Fetcher< DATA_TYPE, N > FetcherType
Type link to the respective fetcher.