iLab Neuromorphic Robotics Toolkit  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GenericBagHelpers.H
Go to the documentation of this file.
1 /*! @file
2  @author Shane Grant
3  @copyright GNU Public License (GPL v3)
4  @section License
5  @verbatim
6  // ////////////////////////////////////////////////////////////////////////
7  // The iLab Neuromorphic Robotics Toolkit (NRT) //
8  // Copyright 2010-2012 by the University of Southern California (USC) //
9  // and the iLab at USC. //
10  // //
11  // iLab - University of Southern California //
12  // Hedco Neurociences Building, Room HNB-10 //
13  // Los Angeles, Ca 90089-2520 - USA //
14  // //
15  // See http://ilab.usc.edu for information about this project. //
16  // ////////////////////////////////////////////////////////////////////////
17  // This file is part of The iLab Neuromorphic Robotics Toolkit. //
18  // //
19  // The iLab Neuromorphic Robotics Toolkit is free software: you can //
20  // redistribute it and/or modify it under the terms of the GNU General //
21  // Public License as published by the Free Software Foundation, either //
22  // version 3 of the License, or (at your option) any later version. //
23  // //
24  // The iLab Neuromorphic Robotics Toolkit is distributed in the hope //
25  // that it will be useful, but WITHOUT ANY WARRANTY; without even the //
26  // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //
27  // PURPOSE. See the GNU General Public License for more details. //
28  // //
29  // You should have received a copy of the GNU General Public License //
30  // along with The iLab Neuromorphic Robotics Toolkit. If not, see //
31  // <http://www.gnu.org/licenses/>. //
32  // ////////////////////////////////////////////////////////////////////////
33  @endverbatim */
34 
35 #ifndef INCLUDE_NRT_CORE_DESIGN_DETAILS_GENERICBAGHELPERS_H
36 #define INCLUDE_NRT_CORE_DESIGN_DETAILS_GENERICBAGHELPERS_H
37 
38 namespace nrt
39 {
40  //! @cond PRIVATE_NEVERDEFINED
41  //! Core GenericBag class used for static asserts
42  class GenericBagCore {};
43 
44  // Base class for GenericBag
45  /* This class has two specializations depending on the number of template parameters.
46 
47  If there are no parameters, a version of the class that essentially does nothing will be
48  instantiated. If there are one or more template parameters, the full version will
49  be instantiated. */
50  template <class ... Args> class GenericBag;
51 
52  //! Base class for StreamableGenericBag
53  /*! This class has two specializations depending on the number of template parameters.
54 
55  If there are no parameters, a version of the class that essentially does nothing will be
56  instantiated. If there are one or more template parameters, the full version will
57  be instantiated. */
58  template <class ... Args> class StreamableGenericBag;
59 
60  //! A helper struct that retrieves a specific class from a bag
61  /*! @tparam height The height of the bag to be searched
62  @tparam RetT The actual desired return type
63  @tparam DecayedT1 The decayed version of RetT
64  @tparam DecayedT2 The decayed version of the FirstType from the searched bag
65 
66  This struct provides one static function, getItem(), which takes a bag to search. This
67  bag will be recursively unpacked, calling getItem() with its tail contents until there is
68  a match between DecayedT1 and DecayedT2. When this match occurs, the head item in the
69  bag will be returned as a RetT, assuming this conversion is possible.
70 
71  If no match is found, a static assert will occur */
72  template <size_t height, class RetT, class DecayedT1, class DecayedT2> struct getClassFromBag;
73 
74  //! A helper struct that retrieves a specific class from a bag, throwing an exception if not found
75  /*! This does exactly the same thing as getClassFromBag, except of having a static_assert, it will
76  throw a runtime exception of type GenericBagException */
77  template <size_t height, class RetT, class DecayedT1, class DecayedT2> struct tryGetClassFromBag;
78 
79  //! A helper struct that recursively calls bagInnerSearch to perform assignment
80  /*! @tparam height1 The height of the first bag
81  @tparam height2 The hieght of the second bag
82  @tparam FirstT2 The head type of the second bag
83  @tparam OtherT2 The tail types of the second bag
84 
85  This struct, in conjunction with bagInnerSearch, will perform an O(n^2) compile time search to
86  perform assignment between two bags with possibly different types. This is provided by
87  the function search, which takes the two bags as input. The first bag will be filled with
88  the matching elements found in the second bag.
89 
90  This works by first calling bagInnerSearch on the current head type from the first bag against
91  the entire second bag, and then recursively calling an outer search on the remaining types in the
92  first bag against the entire second bag */
93  template <size_t height1, size_t height2, class FirstT2, class ... OtherT2> struct bagOuterSearch;
94 
95  //! A helper struct that recursively tries to match and assign a type in one bag to another
96  /*! @tparam height The height of the bag to search
97  @tparam DesiredT The actual desired return type
98  @tparam DecayedT1 The decayed version of DesiredT
99  @tparam DecayedT2 The decayed version of the FirstType from the searched bag
100 
101  This works almost identically to getClassFromBag, except that instead of returning a value we
102  assign into the first bag, and silently fail if we cannot find a match.
103 
104  This works by recursively calling search on the location to assign to and the entire other bag
105  to search. */
106  template <size_t height, class DesiredT, class DecayedT1, class DecayedT2> struct bagInnerSearch;
107 
108  //! A helper struct that recursively calls bagInnerSearch to perform move assignment
109  template <size_t height1, size_t height2, class FirstT2, class ... OtherT2> struct bagOuterSearchMove;
110 
111  //! A helper struct that recursively tries to match and move assign a type in one bag to another
112  template <size_t height, class DesiredT, class DecayedT1, class DecayedT2> struct bagInnerSearchMove;
113 
114  // Gets the specified index from a GenericBag
115  //! Gets the value stored at a specific index in a generic bag
116  /*! @tparam height The height of the item to return
117  @tparam RetT The type to return, which can be gotten with getIndexType
118 
119  This will recursively unpack a bag until it gets to the correct height and then return
120  the first() item of the bag */
121  template <size_t height, class RetT> struct getIndexFromBag;
122 
123  // Gets elements in and out of a StreamableGenericBag
124  template <size_t height> struct streamGenericBagContents;
125 
126  // Helper struct for streaming
127  struct initiateGenericBagStream;
128 
129  // Used to apply functions
130  template <size_t height, class Functor, class RetType> struct expandAndApply;
131 
132  //! Gets the type at a specific index
133  template<size_t Index, class T>
134  struct getIndexType;
135 
136  template<size_t Index, class FirstT, class ... OtherT>
137  struct getIndexType<Index, GenericBag<FirstT, OtherT...>>
138  : getIndexType<Index - 1, GenericBag<OtherT...>> { };
139 
140  template<class FirstT, class ... OtherT>
141  struct getIndexType<0, GenericBag<FirstT, OtherT...>>
142  {
143  typedef FirstT type;
144  };
145 
146  //! Used to get the "correct" type for a requested type
147  template <class DecayedT1, class DecayedT2, class ... Args>
148  struct getReferenceTypeImpl;
149 
150  //! Gets the correct return type for some requested type
151  /*! @tparam T The type to search for
152  @tparam Args The types of the bag to search
153 
154  This provides two compile time values which specify the
155  most correct reference type for a value found in a bag (which means const if necessary, otherwise
156  non constant), as well as a boolean indicating whether a match was found.
157 
158  If a match was not found, the type will not be a reference */
159  template <class T, class ... Args>
160  struct getReferenceType
161  {
162  typedef typename getReferenceTypeImpl<typename std::decay<T>::type,
163  typename std::decay<typename GenericBag<Args...>::FirstType>::type,
164  Args...>::type type;
165 
166  static constexpr bool value = std::is_reference<type>::value; // was the type found?
167  };
168 
169  //! Handles retrieving types during copy construction
170  /*! @tparam Found Was the requested type found in the other bag? See getReferenceType
171  @tparam Reference Are we initializing a reference?
172  @tparam RetT What is our reference type? See getReferenceType
173 
174  This struct provides one function, getItem, which takes a universal reference to some
175  other bag. It will attempt to pull out the correct matching item in the other bag, failing
176  a static_assert if it finds that the bag to be initialized has a reference that is not matched
177  in the other bag */
178  template <bool Found, bool Reference, class RetT>
179  struct copyInitialize;
180 
181  // Type contained by base case of GenericBag
182  class GenericBagNoneType {};
183 
184  // Base case for GenericBag recursion
185  template<> class GenericBag<> : public GenericBagCore
186  {
187  public:
188  // construct
189  GenericBag() = default;
190 
191  // copy
192  template <class ... Args>
193  explicit GenericBag( GenericBag<Args...> const & other ) {}
194 
195  // copy
196  template <class ... Args>
197  explicit GenericBag( StreamableGenericBag<Args...> const & other ) {}
198 
199  // move
200  template <class ... Args>
201  GenericBag( GenericBag<Args...> && other ) {}
202 
203  // move
204  template <class ... Args>
205  GenericBag( StreamableGenericBag<Args...> && other ) {}
206 
207  // assign
208  template <class ... Args>
209  GenericBag & operator=( GenericBag<Args...> const & other )
210  { return *this; }
211 
212  template <class ... Args>
213  GenericBag & operator=( StreamableGenericBag<Args...> const & other )
214  { return *this; }
215 
216  // move assign
217  template <class ... Args>
218  GenericBag & operator=( GenericBag<Args...> && other )
219  { return *this; }
220 
221  template <class ... Args>
222  GenericBag & operator=( StreamableGenericBag<Args...> && other )
223  { return *this; }
224 
225  template <class ... RetTypes, class Functor>
226  GenericBag<RetTypes...> applyFunction( Functor const & f ) const
227  { return GenericBag<RetTypes...>(); }
228 
229  template <class Functor>
230  void applyFunctionInPlace( Functor const & f ) {}
231 
232  protected:
233  template <class ... Args> friend class GenericBag;
234  template <size_t H, class RT, class D1, class D2> friend struct getClassFromBag;
235  template <size_t H, class RT, class D1, class D2> friend struct tryGetClassFromBag;
236  template <size_t H1, size_t H2, class FT2, class ... OT2> friend struct bagOuterSearch;
237  template <size_t H1, class A1, class D1, class D2> friend struct bagInnerSearch;
238  template <size_t H1, size_t H2, class FT2, class ... OT2> friend struct bagOuterSearchMove;
239  template <size_t H1, class A1, class D1, class D2> friend struct bagInnerSearchMove;
240  template <size_t H, class RT> friend struct getIndexFromBag;
241  template <class ... Args> friend class StreamableGenericBag;
242  template <size_t H> friend struct streamGenericBagContents;
243  friend struct initiateGenericBagStream;
244  template <size_t H, class F, class RT> friend struct expandAndApply;
245  template <class T, class ... Args> friend struct getReferenceType;
246  template <class D1, class D2, class ... Args> friend struct getReferenceTypeImpl;
247 
248  typedef GenericBagNoneType FirstType;
249  static constexpr int height = 0;
250  };
251 
252  // base case for stream recursion
253  template <> class StreamableGenericBag<> : public GenericBag<>
254  {
255  public:
256  StreamableGenericBag() = default;
257 
258  // copy
259  template <class ... Args>
260  explicit StreamableGenericBag( GenericBag<Args...> const & other ) {}
261 
262  // copy
263  template <class ... Args>
264  explicit StreamableGenericBag( StreamableGenericBag<Args...> const & other ) {}
265 
266  // move
267  template <class ... Args>
268  StreamableGenericBag( GenericBag<Args...> && other ) {}
269 
270  // move
271  template <class ... Args>
272  StreamableGenericBag( StreamableGenericBag<Args...> && other ) {}
273 
274  // Inherit all assignment operators
275  using GenericBag<>::operator=;
276  };
277 
278  //! @endcond
279 } // namespace nrt
280 
281 #endif // INCLUDE_NRT_CORE_DESIGN_DETAILS_GENERICBAGHELPERS_H