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