TupleHelpers.h
Go to the documentation of this file.
1 /** TupleHelpers help tuples help her make a great meal.
2  *
3  * These helpers provide template gymnastics to bridge compile-time
4  * and run-time access of the collection tuple's. Compile-time
5  * elements are held as types in the tuple, run-time are held as
6  * boost::any in a std::vector<boost::any> or other collection.
7  *
8  */
9 
10 #ifndef WIRECELLUTIL_TUPLEHELPERS
11 #define WIRECELLUTIL_TUPLEHELPERS
12 
13 #include <boost/any.hpp>
14 
15 #include <tuple>
16 #include <vector>
17 #include <deque>
18 #include <string>
19 #include <typeinfo>
20 #include <type_traits>
21 #include <utility>
22 #include <memory>
23 
24 // much inspiration from:
25 // https://www.preney.ca/paul/archives/486
26 // http://loungecpp.wikidot.com/tips-and-tricks:indices
27 // http://stackoverflow.com/questions/31463388/can-someone-please-explain-the-indices-trick
28 
29 /// If we are still before C++14, supply the fodder for doing the "indices trick".
30 #if __cplusplus <= 201103L
31 namespace std {
32  template <std::size_t... Is>
33  struct index_sequence {};
34 
35  template <std::size_t N, std::size_t... Is>
36  struct make_index_sequence : make_index_sequence<N-1, N-1, Is...> {};
37 
38  template <std::size_t... Is>
39  struct make_index_sequence<0, Is...> : index_sequence<Is...> {};
40 }
41 #endif // assume C++14
42 
43 
44 namespace WireCell {
45 
46  /** The basic tuple_helper provides functions to convert a tuple
47  * to a vector of boost::any.
48  *
49  * The doc strings on each helper assume an example tuple type like:
50  *
51  * typedef std::tuple<int,float,double,char,std::string> IFDCS;
52  * tuple_helper<IFDCS> helper;
53  *
54  * For working examples, see test_tuple.cxx.
55  *
56  */
57  template <typename Tuple>
58  struct tuple_helper;
59 
60  template<
61  template <typename...> class T,
62  typename... Types
63  >
64  struct tuple_helper< T<Types...> >
65  {
66  typedef T<Types...> tuple_type;
67 
68  /// Make a new tuple type which each element is a container
69  /// holding type of original tuple element.
70  template< template <typename...> class Container >
71  struct Wrapped {
72  typedef std::tuple<Container<Types>...> type;
73  };
74  template< template <typename...> class Container >
75  struct WrappedConst {
76  typedef std::tuple<Container<const Types>...> type;
77  };
78 
79  typedef std::vector<boost::any> any_vector_type;
80 
81 
82  /** Compile-time mapping of methods on tuple element types
83  *
84  * std::vector<std::string> typenames = helper.type_names();
85  */
86  std::vector<std::string> type_names() {
87  return { std::string(typeid(Types).name())... };
88  }
89 
90  // internal
91  template<std::size_t... Indices>
93  return { boost::any(std::get<Indices>(t))... };
94  }
95 
96  /** Convert a tuple of types to a vector of boost::any.
97  *
98  * IFDCS ifdcs{1,2.2f,3.0e-9,'a',"foo"};
99  * std::vector<boost::any> anyvec = helper.as_any(ifdcs);
100  */
101  any_vector_type as_any(const tuple_type& t) {
103  }
104 
105 
106  // internal
107  template<std::size_t... Indices>
109  return std::make_tuple(boost::any_cast<Types>(anyv[Indices])...);
110  }
111 
112  /** Return a tuple made from the contents of an equivalent vector of boost::any
113  *
114  * // anyvec is from above example
115  * IFDCS t = helper.from_any(anyvec);
116  */
117  tuple_type from_any(const any_vector_type& anyv) {
118  return from_any_impl(anyv, std::make_index_sequence<std::tuple_size<tuple_type>::value>{});
119  }
120 
121  }; // tuple_helpers
122 
123 
124  /** This convert a tuple of types to vector of deque shared_ptr's
125  * of those types.
126  */
127 
128  template <typename Tuple>
130 
131  template<
132  template <typename...> class T,
133  typename... Types
134  >
135  struct shared_queued< T<Types...> >
136  {
137  typedef T<Types...> tuple_type;
138  //typedef tuple_helper<tuple_type> helper;
139 
140  template< template <typename...> class Container >
141  struct WrappedShared {
142  typedef std::tuple<Container< std::shared_ptr<const Types> >...> type;
143  };
144 
145  typedef std::deque<boost::any> any_queue_type;
146 
147  // This is a tuple<deque<shared_ptr<T1>>, deque<shared_ptr<T2>>, ...>
149 
150  // internal, convert a deque<shared_ptr<T>> to a any_queue_type.
151  template<typename Element>
152  any_queue_type as_any_queue_convert(const std::deque< std::shared_ptr<const Element> >& in) {
153  return any_queue_type(in.begin(), in.end());
154  }
155 
156  // internal, index a tuple of typed deque into a vector of any_queues.
157  template<std::size_t... Indices>
158  std::vector< any_queue_type > as_any_queue_impl(const shared_queued_tuple_type& toq,
160  return { as_any_queue_convert(std::get<Indices>(toq))... };
161  }
162 
163  /** Convert a tuple of queues of types to a vector of queues of boost::any.
164  *
165  * typedef typename tuple_helper<IFDCS>::Wrapped<std::deque>::type IFDCS_queues;
166  * IFDCS_queues qs;
167  * auto any_q = as_any_queue(qs);
168  * cerr << "First element from each queue:\n";
169  * cerr << any_cast<int>(any_q[0][0]) << endl;
170  * cerr << any_cast<float>(any_q[1][0]) << endl;
171  * cerr << any_cast<double>(any_q[2][0]) << endl;
172  * cerr << any_cast<char>(any_q[3][0]) << endl;
173  * cerr << any_cast<std::string>(any_q[4][0]) << endl;
174  */
175  std::vector< any_queue_type > as_any_queue(const shared_queued_tuple_type& toq) {
176  return as_any_queue_impl(toq, std::make_index_sequence<std::tuple_size<tuple_type>::value>{});
177  }
178 
179 
180 
181  // internal, cast an any queue to a deque of shared_ptrs of Type.
182  template <typename Type>
183  std::deque< std::shared_ptr<const Type> > from_any_queue_convert(const any_queue_type& aq) {
184  std::deque< std::shared_ptr<const Type> > ret;
185  for (auto a : aq) {
186  ret.push_back(boost::any_cast< std::shared_ptr<const Type> >(a));
187  }
188  return ret;
189  }
190 
191  // internal, index a vector of any queues returning a typed deque<shared_ptr<Type>>.
192  template<std::size_t... Indices>
193  shared_queued_tuple_type from_any_queue_impl(const std::vector< any_queue_type >& vaq, std::index_sequence<Indices...>) {
194  return std::make_tuple(from_any_queue_convert<Types>(vaq[Indices])...);
195  }
196 
197  /** Convert a vector of queues of any to a tuple of queues of type.
198  */
199  shared_queued_tuple_type from_any_queue(const std::vector< any_queue_type >& vaq) {
200  return from_any_queue_impl(vaq, std::make_index_sequence<std::tuple_size<tuple_type>::value>{});
201  }
202 
203  }; // shared_queued
204 
205  // http://stackoverflow.com/a/20711990
206  /** Make an N-tuple of elements all the same type
207  *
208  * type_repeater<3, float>::type blah;
209  */
210  template <std::size_t N, typename T>
211  struct type_repeater {
212  typedef decltype(std::tuple_cat(std::tuple<T>(), typename type_repeater<N-1, T>::type())) type;
213  };
214  template <typename T>
215  struct type_repeater<0,T> {
216  typedef decltype(std::tuple<>()) type;
217  };
218 
219 }
220 
221 
222 #endif
static QCString name
Definition: declinfo.cpp:673
tuple_type from_any_impl(const any_vector_type &anyv, std::index_sequence< Indices... >)
Definition: TupleHelpers.h:108
shared_queued_tuple_type from_any_queue_impl(const std::vector< any_queue_type > &vaq, std::index_sequence< Indices... >)
Definition: TupleHelpers.h:193
shared_queued_tuple_type from_any_queue(const std::vector< any_queue_type > &vaq)
Definition: TupleHelpers.h:199
WrappedShared< std::deque >::type shared_queued_tuple_type
Definition: TupleHelpers.h:148
any_vector_type as_any(const tuple_type &t)
Definition: TupleHelpers.h:101
std::tuple< Container< std::shared_ptr< const Types > >... > type
Definition: TupleHelpers.h:142
std::string string
Definition: nybbler.cc:12
any_vector_type as_any_impl(const tuple_type &t, std::index_sequence< Indices... >)
Definition: TupleHelpers.h:92
STL namespace.
std::vector< std::string > type_names()
Definition: TupleHelpers.h:86
std::vector< any_queue_type > as_any_queue(const shared_queued_tuple_type &toq)
Definition: TupleHelpers.h:175
std::tuple< Container< const Types >... > type
Definition: TupleHelpers.h:76
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition: pointer.h:1124
Definition: Main.h:22
tuple_type from_any(const any_vector_type &anyv)
Definition: TupleHelpers.h:117
std::tuple< Container< Types >... > type
Definition: TupleHelpers.h:72
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1225
any_queue_type as_any_queue_convert(const std::deque< std::shared_ptr< const Element > > &in)
Definition: TupleHelpers.h:152
std::deque< std::shared_ptr< const Type > > from_any_queue_convert(const any_queue_type &aq)
Definition: TupleHelpers.h:183
std::vector< boost::any > any_vector_type
Definition: TupleHelpers.h:79
std::deque< boost::any > any_queue_type
Definition: TupleHelpers.h:145
std::vector< any_queue_type > as_any_queue_impl(const shared_queued_tuple_type &toq, std::index_sequence< Indices... >)
Definition: TupleHelpers.h:158