Geant4 10.7.0
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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{
59 Tp value;
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
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