Arcane  4.1.12.0
User documentation
Loading...
Searching...
No Matches
ServiceOptions.h
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7#ifndef ARCANE_SERVICE_OPTIONS_H
8#define ARCANE_SERVICE_OPTIONS_H
9/*---------------------------------------------------------------------------*/
10/*---------------------------------------------------------------------------*/
11
12#include <memory>
13#include <iostream>
14#include <type_traits>
15#include <array>
16#include <vector>
17#include <tuple>
18#include <map>
19#include <functional>
20
21namespace StrongOptions
22{
23template <typename T, std::size_t N>
24std::ostream& operator<<(std::ostream& o, const std::array<T, N>& a)
25{
26 for (auto x : a)
27 o << " " << x;
28 return o << " ";
29}
30
31template <typename T>
32std::ostream& operator<<(std::ostream& o, const std::vector<T>& a)
33{
34 for (auto x : a)
35 o << " " << x;
36 return o << " ";
37}
38
39/////// Concat array tools
40
41template <std::size_t... Is> struct seq
42{};
43template <std::size_t N, std::size_t... Is>
44struct gen_seq : gen_seq<N - 1, N - 1, Is...>
45{};
46template <std::size_t... Is>
47struct gen_seq<0, Is...> : seq<Is...>
48{};
49
50template <typename T, std::size_t N1, std::size_t... I1, std::size_t N2, std::size_t... I2>
51// Expansion pack
52std::array<T, N1 + N2>
53concat(const std::array<T, N1>& a1, const std::array<T, N2>& a2, seq<I1...>, seq<I2...>)
54{
55 return std::array<T, N1 + N2>{ { a1[I1] }..., { a2[I2] }... };
56}
57
58template <typename T, std::size_t N1, std::size_t N2>
59// Initializer for the recursion
60std::array<T, N1 + N2>
61concat(const std::array<T, N1>& a1, const std::array<T, N2>& a2)
62{
63 return concat(a1, a2, gen_seq<N1>{}, gen_seq<N2>{});
64}
65
66template <typename T, std::size_t N1>
67// Initializer for the recursion
68std::array<T, N1 + 1>
69concat(const std::array<T, N1>& a1, const T& x)
70{
71 return concat(a1, std::array<T, 1>{ { x } }, gen_seq<N1>{}, gen_seq<1>{});
72}
73
74/////////////////
75
77{
78 ////// requiredFixedArray
79 // TODO remove useless copy by std:move from args
80 template <typename T, int N, typename... Args>
81 static std::array<typename T::type, N>
82 requiredFixedArray(Args&&... args)
83 {
84 return Internal<T, N, 0, Args...>::requiredFixedArray(std::array<typename T::type, 0>(), std::move(args)...);
85 }
86
87 template <typename T, int N, int CurN, typename... Args>
88 struct Internal
89 {};
90
91 template <typename T, int N, int CurN, typename Head, typename... Tail>
92 struct Internal<T, N, CurN, Head, Tail...>
93 {
94 static std::array<typename T::type, N>
95 requiredFixedArray(const std::array<typename T::type, CurN>& r, Head&&, Tail&&... args)
96 {
97 return Internal<T, N, CurN, Tail...>::requiredFixedArray(r, std::move(args)...);
98 }
99 };
100
101 template <typename T, int N, int CurN, typename... Tail>
102 struct Internal<T, N, CurN, T, Tail...>
103 {
104 static std::array<typename T::type, N>
105 requiredFixedArray(const std::array<typename T::type, CurN>& r, T&& t, Tail&&... args)
106 {
107 return Internal<T, N, CurN + 1, Tail...>::requiredFixedArray(concat(r, t.value), std::move(args)...);
108 }
109 };
110
111 template <typename T, int N, int CurN>
112 struct Internal<T, N, CurN>
113 {
114 static std::array<typename T::type, N>
115 requiredFixedArray(const std::array<typename T::type, CurN>& r)
116 {
117 static_assert(CurN == N, "Invalid required parameter count");
118 return std::move(r);
119 }
120 };
121
122 /* ////// requiredVariableArray
123 template<typename T, int Nmin, int Nmax, typename... Args>
124 static std::vector<typename T::type>
125 requiredVariableArray(Args&&... args)
126 {
127 return Internal2<T,Nmin,Nmax,0,Args...>::requiredVariableArray(std::vector<typename T::type>{}, std::move(args)...);
128 }
129
130 template<typename T, int Nmin, int Nmax, int CurN, typename... Args>
131 struct Internal2 { };
132
133 template<typename T, int Nmin, int Nmax, int CurN, typename Head, typename... Tail>
134 struct Internal2<T,Nmin,Nmax,CurN,Head,Tail...>
135 {
136 static std::vector<typename T::type> &&
137 requiredVariableArray(std::vector<typename T::type> && r, Head && t, Tail &&... args)
138 {
139 return Internal2<T,Nmin,Nmax,CurN,Tail...>::requiredVariableArray(std::move(r), std::move(args)...);
140 }
141 };
142
143 template<typename T, int Nmin, int Nmax, int CurN, typename... Tail>
144 struct Internal2<T,Nmin,Nmax,CurN,T,Tail...>
145 {
146 static std::vector<typename T::type> &&
147 requiredVariableArray(std::vector<typename T::type> && r, T && t, Tail &&... args)
148 {
149 r.emplace_back(t.value);
150 return Internal2<T,Nmin,Nmax,CurN+1,Tail...>::requiredVariableArray(std::move(r),std::move(args)...);
151 }
152 };
153
154 template<typename T, int Nmin, int Nmax, int CurN>
155 struct Internal2<T,Nmin,Nmax,CurN>
156 {
157 static std::vector<typename T::type> &&
158 requiredVariableArray(std::vector<typename T::type> && r)
159 {
160 static_assert(CurN>=Nmin && CurN<=Nmax, "Invalid required parameter count");
161 return std::move(r);
162 }
163 };
164*/
165 ////// requiredVariableArray
166 template <typename T, int Nmin, int Nmax, typename... Args>
168 requiredVariableArray(Args&&... args)
169 {
171 }
172
173 template <typename T, int Nmin, int Nmax, int CurN, typename... Args>
175 {};
176
177 template <typename T, int Nmin, int Nmax, int CurN, typename Head, typename... Tail>
178 struct Internal2<T, Nmin, Nmax, CurN, Head, Tail...>
179 {
181 requiredVariableArray(Arcane::UniqueArray<typename T::type>&& r, [[maybe_unused]] Head&& t, Tail&&... args)
182 {
183 return Internal2<T, Nmin, Nmax, CurN, Tail...>::requiredVariableArray(std::move(r), std::move(args)...);
184 }
185 };
186
187 // TODO : Use r.emplace_back when Arcane::Array allows it
188 template <typename T, int Nmin, int Nmax, int CurN, typename... Tail>
189 struct Internal2<T, Nmin, Nmax, CurN, T, Tail...>
190 {
192 requiredVariableArray(Arcane::UniqueArray<typename T::type>&& r, T&& t, Tail&&... args)
193 {
194 r.add(t.value);
195 return Internal2<T, Nmin, Nmax, CurN + 1, Tail...>::requiredVariableArray(std::move(r), std::move(args)...);
196 }
197 };
198
199 template <typename T, int Nmin, int Nmax, int CurN>
200 struct Internal2<T, Nmin, Nmax, CurN>
201 {
203 requiredVariableArray(Arcane::UniqueArray<typename T::type>&& r)
204 {
205 static_assert(CurN >= Nmin && (Nmax == -1 || CurN <= Nmax), "Invalid required parameter count");
206 return std::move(r);
207 }
208 };
209
210 ////// optionalSimple
211 template <typename T, typename... Args>
212 static bool
213 optionalSimple(typename T::type& r, Args&&... args)
214 {
215 return Internal3<T, 0, Args...>::optionalSimple(r, std::move(args)...);
216 }
217
218 template <typename T, int CurN, typename... Args>
220 {};
221
222 template <typename T, int CurN, typename Head, typename... Tail>
223 struct Internal3<T, CurN, Head, Tail...>
224 {
225 static bool
226 optionalSimple(typename T::type& r, Head&&, Tail&&... args)
227 {
228 return Internal3<T, CurN, Tail...>::optionalSimple(r, std::move(args)...);
229 }
230 };
231
232 template <typename T, int CurN, typename... Tail>
233 struct Internal3<T, CurN, T, Tail...>
234 {
235 static bool
236 optionalSimple(typename T::type& r, T&& t, Tail&&... args)
237 {
238 r = t.value;
239 return Internal3<T, CurN + 1, Tail...>::optionalSimple(r, std::move(args)...);
240 }
241 };
242
243 template <typename T, int CurN>
244 struct Internal3<T, CurN>
245 {
246 static bool
247 optionalSimple([[maybe_unused]] typename T::type& r)
248 {
249 static_assert(CurN <= 1, "Invalid required parameter count");
250 return CurN == 1;
251 }
252 };
253
254 ////// Restrict
255 template <typename AllowedTypes, typename... Args>
256 static void
257 checkRestriction(const Args&... args)
258 {
260 }
261
262 template <typename AllowedTypes, typename... Args>
264 {};
265
266 template <typename... AllowedTypes, typename Head, typename... Tail>
267 struct Internal4<std::tuple<AllowedTypes...>, Head, Tail...>
268 {
269 static void
270 checkRestriction([[maybe_unused]] const Head& h, const Tail&... tail)
271 {
272 static_assert(Internal44<Head, AllowedTypes...>::checkType, "Illegal option");
273 return Internal4<std::tuple<AllowedTypes...>, Tail...>::checkRestriction(tail...);
274 }
275 };
276
277 template <typename... AllowedTypes>
278 struct Internal4<std::tuple<AllowedTypes...>>
279 {
280 static void
281 checkRestriction()
282 {
283 return;
284 }
285 };
286
287 template <typename Arg, typename... AllowedTypes>
289 {};
290
291 template <typename Arg, typename Head, typename... Tail>
292 struct Internal44<Arg, Head, Tail...>
293 {
294 static const bool checkType = Internal44<Arg, Head>::checkType || Internal44<Arg, Tail...>::checkType;
295 };
296
297 template <typename Arg, typename Head>
298 struct Internal44<Arg, Head>
299 {
300 static const bool checkType = std::is_same<Arg, Head>::value;
301 };
302
303 template <typename Arg>
304 struct Internal44<Arg>
305 {
306 static const bool checkType = false;
307 };
308};
309
310////////////
311
312template <typename Name, typename Type>
314{
315 typedef Name name;
316 typedef Type type;
317 type value;
318
319 //OptionValue<Name, Type> && operator=(const Type & v) { value = v; return std::move(*this); }
320 // friend std::ostream & operator<<(std::ostream & o, const OptionValue<Name, Type> & x) { return o << x.value; }
321};
322
323template <typename Name, typename Type>
325{
326 OptionValue<Name, Type> operator=(const Type&& value) { return OptionValue<Name, Type>{ value }; }
327 OptionValue<Name, Type> operator=(const Type& value) { return OptionValue<Name, Type>{ value }; }
328 OptionValue<Name, Type> operator=(Type& value) { return OptionValue<Name, Type>{ value }; }
329
330 //OptionValue<Name, Type> operator=(Type && value) { // possible to optimize in one line as above
331 //OptionValue<Name,Type> myopval{std::move(value)};
332 //return std::move(myopval);
333 //}
334};
335
336#define DECLARE_OPTION_EXTERN(name, type) \
337 namespace tag \
338 { \
339 struct name##_t; \
340 } \
341 typedef OptionValue<tag::name##_t, type> name##_; \
342 ARCANE_CORE_EXPORT extern OptionProxy<tag::name##_t, type> _##name;
343
344#define DECLARE_OPTION(name, type) \
345 namespace tag \
346 { \
347 struct name##_t; \
348 } \
349 typedef OptionValue<tag::name##_t, type> name##_; \
350 OptionProxy<tag::name##_t, type> _##name;
351
352}; // namespace StrongOptions
353
354#if !defined(ARCANE_JOIN_HELPER2)
355#define ARCANE_JOIN_HELPER2(a, b) a##b
356#endif
357
358#if !defined(ARCANE_JOIN_HELPER)
359#define ARCANE_JOIN_HELPER(a, b) ARCANE_JOIN_HELPER2(a, b)
360#endif
361
362#if !defined(ARCANE_JOIN_WITH_LINE)
363#define ARCANE_JOIN_WITH_LINE(a) ARCANE_JOIN_HELPER(a, __LINE__)
364#endif
365
366/*---------------------------------------------------------------------------*/
367/*---------------------------------------------------------------------------*/
368
369template <typename Interface>
371{
372 public:
373
374 static std::unique_ptr<Interface>
375 create(const std::string& name)
376 {
377 const std::map<std::string, ctor_functor>& ctor_functors = instance()->m_ctor_functors;
378 auto finder = ctor_functors.find(name);
379 /*if (finder == ctor_functors.end())
380 throw InstanceParameterException{stringer("Cannot find implementation '", name, "' for interface ", typeid(Interface).name())};*/
381 return std::unique_ptr<Interface>(finder->second());
382 }
383
384 public:
385
386 typedef std::function<Interface*()> ctor_functor;
387
388 static void
389 registerImplementation(const std::string& name, const ctor_functor& ctor)
390 {
391 instance()->m_ctor_functors[name] = ctor;
392 }
393
394 private:
395
396 static std::unique_ptr<InstanceBuilder> m_instance;
398 instance()
399 {
400 if (!m_instance)
401 m_instance.reset(new InstanceBuilder<Interface>());
402 return m_instance.get();
403 }
404
405 private:
406
407 std::map<std::string, ctor_functor> m_ctor_functors;
408};
409
410/*---------------------------------------------------------------------------*/
411/*---------------------------------------------------------------------------*/
412
413template <typename Interface, typename Class, typename SrongOptionClass>
414struct InstanceRegisterer
415{
416 InstanceRegisterer(const std::string& name)
417 {
418 InstanceBuilder<Interface>::registerImplementation(name, []() -> Interface* {
419 return new Class(std::move(std::unique_ptr<SrongOptionClass>(new SrongOptionClass{})));
420 });
421 }
422};
423
424/*---------------------------------------------------------------------------*/
425/*---------------------------------------------------------------------------*/
426
427#endif
void add(ConstReferenceType val)
Adds element val to the end of the array.
1D data vector with value semantics (STL style).