Geant4-11
Tuple.hh
Go to the documentation of this file.
1// MIT License
2// Copyright (c) 2020 Jonathan R. Madsen
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9// The above copyright notice and this permission notice shall be included in
10// all copies or substantial portions of the Software.
11// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
16// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17// SOFTWARE.
18
19#pragma once
20
21#include <cstring>
22#include <functional>
23#include <tuple>
24#include <type_traits>
25
26namespace PTL
27{
28template <typename Tp, typename Up>
30{
31 static constexpr bool value = sizeof(Tp) < sizeof(Up);
32};
33
34//======================================================================================//
35
36// CTValue == compile-time value
37//
38// useful to work with sequences of compile-time values, such as the bounds of a
39// multidimensional array or indices into another typelist.
40
41template <typename Tp, Tp Value>
42struct CTValue
43{
44 static constexpr Tp value = Value;
45};
46
47//======================================================================================//
48
49template <std::size_t Height, typename Tp,
50 bool = std::is_class<Tp>::value && !std::is_final<Tp>::value>
52
53//--------------------------------------------------------------------------------------//
54// specialization that does not satisfy is_class<> and not is_final<>
55//
56template <std::size_t Height, typename Tp>
57class TupleElt<Height, Tp, false>
58{
60
61public:
62 TupleElt() = default;
63
64 template <typename Up>
65 TupleElt(Up&& other)
66 : value(std::forward<Up>(other))
67 {}
68
69 Tp& get() { return value; }
70 Tp const& get() const { return value; }
71};
72
73//--------------------------------------------------------------------------------------//
74// specialization that does satisfy is_class<> and not is_final<>
75//
76template <std::size_t Height, typename Tp>
77class TupleElt<Height, Tp, true> : private Tp
78{
79public:
80 TupleElt() = default;
81
82 template <typename Up>
83 explicit TupleElt(Up&& other)
84 : Tp(std::forward<Up>(other))
85 {}
86
87 Tp& get() { return *this; }
88 const Tp& get() const { return *this; }
89};
90
91//======================================================================================//
92
93template <unsigned H, typename T>
94T&
96{
97 return te.get();
98}
99
100//======================================================================================//
101
102template <typename... Types>
103class Tuple;
104
105//--------------------------------------------------------------------------------------//
106
107// recursive case:
108template <typename Head, typename... Tail>
109class Tuple<Head, Tail...>
110: private TupleElt<sizeof...(Tail), Head>
111, private Tuple<Tail...>
112{
113 template <unsigned I, typename... Elements>
114 friend auto get(Tuple<Elements...>& t)
115 -> decltype(get_height<sizeof...(Elements) - I - 1>(t));
116
117public:
118 Head& head() { return static_cast<HeadElt*>(this)->get(); }
119 const Head& head() const { return static_cast<HeadElt const*>(this)->get(); }
120 Tuple<Tail...>& tail() { return *this; }
121 const Tuple<Tail...>& tail() const { return *this; }
122
123private:
124 using HeadElt = TupleElt<sizeof...(Tail), Head>;
125};
126
127//--------------------------------------------------------------------------------------//
128// basis case:
129template <>
130class Tuple<>
131{
132 // no storage required
133};
134
135//--------------------------------------------------------------------------------------//
136
137template <unsigned I, typename... Elements>
138auto
139get(Tuple<Elements...>& t) -> decltype(get_height<sizeof...(Elements) - I - 1>(t))
140{
141 return get_height<sizeof...(Elements) - I - 1>(t);
142}
143
144template <typename... Tp>
145using TypeList = Tuple<Tp...>;
146
147//======================================================================================//
148
149template <typename List>
151{
152public:
153 static constexpr bool value = false;
154};
155
156template <>
158{
159public:
160 static constexpr bool value = true;
161};
162
163template <typename List, typename NewElement>
165
166template <typename... Elements, typename NewElement>
167class PushBackT<Tuple<Elements...>, NewElement>
168{
169public:
170 using Type = Tuple<Elements..., NewElement>;
171};
172
173template <typename List, typename NewElement>
175
176template <typename List>
178
179template <typename Head, typename... Tail>
180class PopFrontT<std::tuple<Head, Tail...>>
181{
182public:
183 using Type = std::tuple<Tail...>;
184};
185
186template <typename List>
188
189template <typename List, typename Element>
191
192template <typename... Types, typename Element>
193class PushFrontT<std::tuple<Types...>, Element>
194{
195public:
196 using Type = std::tuple<Element, Types...>;
197};
198
199template <typename List, typename NewElement>
201
202template <typename... Types, typename V>
203PushFront<std::tuple<Types...>, V>
204pushFront(std::tuple<Types...> const& tuple, V const& value)
205{
206 return PushFront<std::tuple<Types...>, V>(value, tuple);
207}
208
209template <typename T, T... Values>
211{};
212
213template <typename... Types>
214struct Front;
215
216template <typename FrontT, typename... Types>
217struct Front<FrontT, Types...>
218{
219 using Type = FrontT;
220};
221
222template <typename... Types>
223struct Back;
224
225template <typename BackT, typename... Types>
226struct Back<Types..., BackT>
227{ // ERROR: pack expansion not at the end of
228 using Type = BackT; // template argument list
229};
230
231//======================================================================================//
232
233template <typename List, template <typename T> class MetaFun,
234 bool Empty = IsEmpty<List>::value>
236
237// recursive case:
238template <typename List, template <typename T> class MetaFun>
239class TransformT<List, MetaFun, false>
240: public PushFrontT<typename TransformT<PopFront<List>, MetaFun>::Type,
241 typename MetaFun<Front<List>>::Type>
242{};
243
244// basis case:
245template <typename List, template <typename T> class MetaFun>
246class TransformT<List, MetaFun, true>
247{
248public:
249 using Type = List;
250};
251
252template <typename List, template <typename T> class MetaFun>
254
255template <typename... Elements, template <typename T> class MetaFun>
256class TransformT<Tuple<Elements...>, MetaFun, false>
257{
258public:
260};
261
262template <size_t N>
264{
265 template <typename Func, typename Head, typename... Tail>
266 static inline auto forward(Func&& func, Head&& head, Tail&&... tail)
268 std::forward<Func>(func), std::forward<Head>(head),
269 std::get<N - 1>(std::forward<Head>(head)), std::forward<Tail>(tail)...))
270 {
272 std::forward<Func>(func), std::forward<Head>(head),
273 std::get<N - 1>(std::forward<Head>(head)), std::forward<Tail>(tail)...);
274 }
275};
276
277//======================================================================================//
278
279template <>
281{
282 template <typename Func, typename Head, typename... Tail>
283 static inline auto forward(Func&& func, Head&&, Tail&&... tail)
284 -> decltype(std::forward<Func>(func)(std::forward<Tail>(tail)...))
285 {
286 return std::forward<Func>(func)(std::forward<Tail>(tail)...);
287 }
288};
289
290//======================================================================================//
291
292template <size_t N>
294{
295 template <typename Func, typename Head>
296 static inline auto apply(Func&& func, Head&& head)
297 {
298 std::forward<Func>(func)(std::forward<Head>(head));
299 }
300
301 template <typename Func, typename Head, typename... Tail>
302 static inline void apply(Func&& func, Head&& head, Tail&&... tail)
303 {
304 std::forward<Func>(func)(std::forward<Head>(head));
305 ForEachTupleArg<N - 1>::apply(std::forward<Func>(func),
306 std::forward<Tail>(tail)...);
307 }
308};
309
310//======================================================================================//
311
312template <typename Func, typename Tuple>
313void
314for_each_tuple_arg(Func&& func, Tuple&& _tuple)
315{
317 std::forward<Func>(func), std::forward<std::tuple>(_tuple));
318}
319
320//======================================================================================//
321
322template <typename Func, typename Tuple, std::size_t Head>
323inline auto
324InvokeSequence_impl(const Func& func, const Tuple& data)
325{
326 func(std::get<Head>(data));
327}
328
329//======================================================================================//
330
331template <typename Func, typename Tuple, std::size_t Head, std::size_t... Tail>
332inline auto
333InvokeSequence_impl(const Func& func, const Tuple& data)
334{
335 func(std::get<Head>(data));
336 InvokeSequence_impl<Func, Tuple, Tail...>(func, data);
337}
338
339//======================================================================================//
340
341template <typename Func, typename Tuple, std::size_t N = std::tuple_size<Tuple>::value,
342 typename Indices = std::make_index_sequence<N>>
343inline auto
344InvokeSequence(const Func& func, const Tuple& data)
345{
346 return InvokeSequence_impl(func, data);
347}
348
349//======================================================================================//
350
351// Convert array into a tuple
352template <typename Container, std::size_t... N>
353inline auto
354ContainerToTuple_impl(const Container& tasks, std::index_sequence<N...>)
355{
356 return std::make_tuple(tasks[N]...);
357}
358
359//======================================================================================//
360
361template <std::size_t N, typename Container,
362 typename Indices = std::make_index_sequence<N>>
363inline auto
364ContainerToTuple(const Container& tasks)
365{
366 return ContainerToTuple_impl(tasks, Indices{});
367}
368
369//======================================================================================//
370
371template <typename... Args>
373{
374 static std::tuple<> get(const std::tuple<>&) { return std::tuple<>{}; }
375
376 template <typename... SubArgs>
377 static std::tuple<SubArgs...> get(const std::tuple<Args...>& t)
378 {
379 return std::tuple<SubArgs...>{ std::get<SubArgs>(t)... };
380 }
381};
382
383template <typename Head>
384inline void
385tuple_transform(const std::function<void(const Head&)>& pred,
386 const std::tuple<Head>& data)
387{
388 pred(std::get<0>(data));
389}
390
391template <typename Head, typename... Tail>
392inline void
393tuple_transform(const std::function<void(const Head&)>& pred,
394 const std::tuple<Head, Tail...>& data)
395{
396 pred(std::get<0>(data));
397 auto subset = tuple_subset<Head, Tail...>::template get<Tail...>(data);
398 tuple_transform<Tail...>(pred, std::forward<decltype(subset)>(subset));
399}
400
401template <typename Head, typename... Tail>
403{
404 using Function = std::function<void(Head)>;
405 template <typename TupleType>
406 static void apply(const Function& func, const TupleType& t)
407 {
408 func(std::get<0>(t));
409 PopFront<TupleType> nt = std::tuple<Tail...>{ std::get<Tail>(t)... };
411 }
412};
413
414template <typename Head>
415struct transform_tuple<Head>
416{
417 using Function = std::function<void(Head)>;
418 template <typename TupleType>
419 static void apply(const Function& func, const TupleType& t)
420 {
421 func(std::get<0>(t));
422 }
423};
424
425//======================================================================================//
426
427template <typename Func, typename... Elements, unsigned... Indices>
428auto
429applyImpl(Func func, std::tuple<Elements...> const& t, Valuelist<unsigned, Indices...>)
430 -> decltype(func(std::get<Indices>(t)...))
431{
432 return func(std::get<Indices>(t)...);
433}
434
435template <typename Func, typename... Elements, unsigned N = sizeof...(Elements)>
436auto
437apply(Func func, std::tuple<Elements...> const& t)
438 -> decltype(applyImpl(func, t, std::make_index_sequence<N>()))
439{
440 return applyImpl(func, t, std::make_index_sequence<N>());
441}
442
443} // namespace PTL
G4double(* function)(G4double)
static constexpr bool value
Definition: Tuple.hh:153
std::tuple< Element, Types... > Type
Definition: Tuple.hh:196
Tp const & get() const
Definition: Tuple.hh:70
const Tp & get() const
Definition: Tuple.hh:88
const Head & head() const
Definition: Tuple.hh:119
const Tuple< Tail... > & tail() const
Definition: Tuple.hh:121
Tuple< Tail... > & tail()
Definition: Tuple.hh:120
Definition: AutoLock.hh:254
typename PopFrontT< List >::Type PopFront
Definition: Tuple.hh:187
auto InvokeSequence(const Func &func, const Tuple &data)
Definition: Tuple.hh:344
auto apply(Func func, std::tuple< Elements... > const &t) -> decltype(applyImpl(func, t, std::make_index_sequence< N >()))
Definition: Tuple.hh:437
PushFront< std::tuple< Types... >, V > pushFront(std::tuple< Types... > const &tuple, V const &value)
Definition: Tuple.hh:204
auto ContainerToTuple_impl(const Container &tasks, std::index_sequence< N... >)
Definition: Tuple.hh:354
void tuple_transform(const std::function< void(const Head &)> &pred, const std::tuple< Head > &data)
Definition: Tuple.hh:385
void for_each_tuple_arg(Func &&func, Tuple &&_tuple)
Definition: Tuple.hh:314
typename PushBackT< List, NewElement >::Type PushBack
Definition: Tuple.hh:174
auto get(Tuple< Elements... > &t) -> decltype(get_height< sizeof...(Elements) - I - 1 >(t))
Definition: Tuple.hh:139
auto InvokeSequence_impl(const Func &func, const Tuple &data)
Definition: Tuple.hh:324
auto applyImpl(Func func, std::tuple< Elements... > const &t, Valuelist< unsigned, Indices... >) -> decltype(func(std::get< Indices >(t)...))
Definition: Tuple.hh:429
typename TransformT< List, MetaFun >::Type Transform
Definition: Tuple.hh:253
T & get_height(TupleElt< H, T > &te)
Definition: Tuple.hh:95
typename PushFrontT< List, NewElement >::Type PushFront
Definition: Tuple.hh:200
auto ContainerToTuple(const Container &tasks)
Definition: Tuple.hh:364
static constexpr Tp value
Definition: Tuple.hh:44
static void apply(Func &&func, Head &&head, Tail &&... tail)
Definition: Tuple.hh:302
static auto apply(Func &&func, Head &&head)
Definition: Tuple.hh:296
static auto forward(Func &&func, Head &&, Tail &&... tail) -> decltype(std::forward< Func >(func)(std::forward< Tail >(tail)...))
Definition: Tuple.hh:283
static auto forward(Func &&func, Head &&head, Tail &&... tail) -> decltype(ForwardTupleAsArgs< N - 1 >::forward(std::forward< Func >(func), std::forward< Head >(head), std::get< N - 1 >(std::forward< Head >(head)), std::forward< Tail >(tail)...))
Definition: Tuple.hh:266
static constexpr bool value
Definition: Tuple.hh:31
std::function< void(Head)> Function
Definition: Tuple.hh:417
static void apply(const Function &func, const TupleType &t)
Definition: Tuple.hh:419
std::function< void(Head)> Function
Definition: Tuple.hh:404
static void apply(const Function &func, const TupleType &t)
Definition: Tuple.hh:406
static std::tuple get(const std::tuple<> &)
Definition: Tuple.hh:374
static std::tuple< SubArgs... > get(const std::tuple< Args... > &t)
Definition: Tuple.hh:377