iLab Neuromorphic Robotics Toolkit  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GenericBagImpl.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_GENERICBAGIMPL_H
36 #define INCLUDE_NRT_CORE_DESIGN_DETAILS_GENERICBAGIMPL_H
37 
38 // DO NOT INCLUDE ANY HEADERS HERE - YOU ARE CURRENTLY INSIDE THE NRT NAMESPACE!
39 
40 inline nrt::exception::GenericBagException::GenericBagException( std::string const & field ) noexcept
41  try : nrt::exception::Exception( "Error GenericBagException, and further error while constructing the exception" ),
42  itsField( field )
43 {
44  std::ostringstream ss;
45  ss << "Trying to access non existant field " << itsField << " in generic bag";
46 
47  whatstring = ss.str();
48  whatptr = whatstring.c_str();
49 } catch( ... ) { }
50 
51 inline nrt::exception::GenericBagException::~GenericBagException() noexcept
52 { }
53 
54 template <class FirstT, class ... OtherT> inline
55 GenericBag<FirstT, OtherT...>::GenericBag() : GenericBag<OtherT...>(), itsFirst()
56 { }
57 
58 template <class FirstT, class ... OtherT> inline
59 GenericBag<FirstT, OtherT...>::GenericBag( FirstT const & first, OtherT const & ... other ) :
60  GenericBag<OtherT...>( other...), itsFirst( first )
61 { }
62 
63 template <class FirstT, class ... OtherT>
64 template <class FirstT2, class ... OtherT2> inline
65 GenericBag<FirstT, OtherT...>::GenericBag( GenericBag<FirstT2, OtherT2...> const & other ) :
66  GenericBag<OtherT...>( other ),
67  itsFirst( copyInitialize<getReferenceType<FirstT, FirstT2, OtherT2...>::value, // found?
68  std::is_reference<FirstT>::value, // are we a reference
69  typename getReferenceType<FirstT, FirstT2, OtherT2...>::type>::getItem( other ) ) // what is our type
70 { }
71 
72 template <class FirstT, class ... OtherT>
73 template <class FirstT2, class ... OtherT2> inline
74 GenericBag<FirstT, OtherT...>::GenericBag( StreamableGenericBag<FirstT2, OtherT2...> const & other ) :
75  GenericBag<OtherT...>( other ),
76  itsFirst( copyInitialize<getReferenceType<FirstT, FirstT2, OtherT2...>::value, // found?
77  std::is_reference<FirstT>::value, // are we a reference
78  typename getReferenceType<FirstT, FirstT2, OtherT2...>::type>::getItem( other ) ) // what is our type
79 { }
80 
81 template <class FirstT, class ... OtherT> inline
82 GenericBag<FirstT, OtherT...>::GenericBag( GenericBag<> const & other ) :
83  GenericBag<OtherT...>(), itsFirst()
84 { }
85 
86 template <class FirstT, class ... OtherT> inline
87 GenericBag<FirstT, OtherT...>::GenericBag( StreamableGenericBag<> const & other ) :
88  GenericBag<OtherT...>(), itsFirst()
89 { }
90 
91 template <class FirstT, class ... OtherT>
92 template <class FirstT2, class ... OtherT2> inline
93 GenericBag<FirstT, OtherT...>::GenericBag( GenericBag<FirstT2, OtherT2...> && other ) :
94  GenericBag<OtherT...>( std::forward<GenericBag<FirstT2, OtherT2...>>( other ) ),
95  itsFirst( std::move( copyInitialize<getReferenceType<FirstT, FirstT2, OtherT2...>::value, // found?
96  std::is_reference<FirstT>::value, // are we a reference
97  typename getReferenceType<FirstT, FirstT2, OtherT2...>::type>::getItem(
98  std::forward<GenericBag<FirstT2, OtherT2...>>( other ) ) ) ) // what is our type
99 { }
100 
101 template <class FirstT, class ... OtherT>
102 template <class FirstT2, class ... OtherT2> inline
103 GenericBag<FirstT, OtherT...>::GenericBag( StreamableGenericBag<FirstT2, OtherT2...> && other ) :
104  GenericBag<OtherT...>( std::forward<StreamableGenericBag<FirstT2, OtherT2...>>( other ) ),
105  itsFirst( std::move( copyInitialize<getReferenceType<FirstT, FirstT2, OtherT2...>::value, // found?
106  std::is_reference<FirstT>::value, // are we a reference
107  typename getReferenceType<FirstT, FirstT2, OtherT2...>::type>::getItem(
108  std::forward<StreamableGenericBag<FirstT2, OtherT2...>>( other ) ) ) ) // what is our type
109 { }
110 
111 template <class FirstT, class ... OtherT> inline
112 GenericBag<FirstT, OtherT...>::GenericBag( GenericBag<> && other ) :
113  GenericBag<OtherT...>(), itsFirst()
114 { }
115 
116 template <class FirstT, class ... OtherT> inline
117 GenericBag<FirstT, OtherT...>::GenericBag( StreamableGenericBag<> && other ) :
118  GenericBag<OtherT...>(), itsFirst()
119 { }
120 
121 template <class FirstT, class ... OtherT>
122 template <class FirstT2, class ... OtherT2> inline
123 GenericBag<FirstT, OtherT...> & GenericBag<FirstT, OtherT...>::operator=(
124  GenericBag<FirstT2, OtherT2...> const & other )
125 {
126  bagOuterSearch<height, GenericBag<FirstT2, OtherT2...>::height, FirstT2, OtherT2...>::template
127  search( *this, other );
128 
129  return *this;
130 }
131 
132 template <class FirstT, class ... OtherT>
133 template <class FirstT2, class ... OtherT2> inline
134 GenericBag<FirstT, OtherT...> & GenericBag<FirstT, OtherT...>::operator=(
135  StreamableGenericBag<FirstT2, OtherT2...> const & other )
136 {
137  bagOuterSearch<height, GenericBag<FirstT2, OtherT2...>::height, FirstT2, OtherT2...>::template
138  search( *this, other );
139 
140  return *this;
141 }
142 
143 //! @cond PRIVATE_NEVERDEFINED
144 template <class FirstT, class ... OtherT> inline
145 auto GenericBag<FirstT, OtherT...>::operator=( GenericBag<> const & other ) -> GenericBag &
146 { return *this; }
147 
148 template <class FirstT, class ... OtherT> inline
149 auto GenericBag<FirstT, OtherT...>::operator=( StreamableGenericBag<> const & other ) -> GenericBag &
150 { return *this; }
151 
152 template <class FirstT, class ... OtherT> inline
153 auto GenericBag<FirstT, OtherT...>::operator=( GenericBag<> && other ) -> GenericBag &
154 { return *this; }
155 
156 template <class FirstT, class ... OtherT> inline
157 auto GenericBag<FirstT, OtherT...>::operator=( StreamableGenericBag<> && other ) -> GenericBag &
158 { return *this; }
159 //! @endcond
160 
161 template <class FirstT, class ... OtherT>
162 template <class FirstT2, class ... OtherT2> inline
163 GenericBag<FirstT, OtherT...> & GenericBag<FirstT, OtherT...>::operator=(
164  GenericBag<FirstT2, OtherT2...> && other )
165 {
166  bagOuterSearchMove<height, GenericBag<FirstT2, OtherT2...>::height, FirstT2, OtherT2...>::template
167  search( *this, std::forward<GenericBag<FirstT2, OtherT2...>>( other ) );
168 
169  return *this;
170 }
171 
172 template <class FirstT, class ... OtherT>
173 template <class FirstT2, class ... OtherT2> inline
174 GenericBag<FirstT, OtherT...> & GenericBag<FirstT, OtherT...>::operator=(
175  StreamableGenericBag<FirstT2, OtherT2...> && other )
176 {
177  bagOuterSearchMove<height, GenericBag<FirstT2, OtherT2...>::height, FirstT2, OtherT2...>::template
178  search( *this, std::forward<StreamableGenericBag<FirstT2, OtherT2...>>( other ) );
179 
180  return *this;
181 }
182 
183 template <class FirstT, class ... OtherT>
184 template <class ... RetTypes, class Functor> inline
185 GenericBag<RetTypes...> GenericBag<FirstT, OtherT...>::applyFunction( Functor && f ) const
186 {
187  static_assert( sizeof...(RetTypes) == height, "Resulting GenericBag must be a 1:1 mapping" );
188 
189  return expandAndApply<height, Functor, GenericBag<RetTypes...>>::template apply( std::forward<Functor>( f ), *this );
190 }
191 
192 template <class FirstT, class ... OtherT>
193 template <class Functor> inline
195 {
196  return expandAndApply<height, Functor, void>::template apply( std::forward<Functor>( f ), *this );
197 }
198 
199 template <class FirstT, class ... OtherT>
200 template <class T> inline
201 auto GenericBag<FirstT, OtherT...>::get() -> typename getReferenceType<T, FirstT, OtherT...>::type
202 {
203  return getClassFromBag<height, typename getReferenceType<T, FirstT, OtherT...>::type, typename std::decay<T>::type, typename std::decay<FirstT>::type>::getItem( *this );
204 }
205 
206 template <class FirstT, class ... OtherT>
207 template <class T> inline
208 typename std::decay<T>::type const & GenericBag<FirstT, OtherT...>::get() const
209 {
210  return getClassFromBag<height, typename std::decay<T>::type const &, typename std::decay<T>::type, typename std::decay<FirstT>::type>::getItem( *this );
211 }
212 
213 template <class FirstT, class ... OtherT>
214 template <size_t Index> inline
215 auto GenericBag<FirstT, OtherT...>::get() -> typename getIndexType<Index, GenericBag>::type &
216 {
217  return getIndexFromBag<Index, typename getIndexType<Index, GenericBag>::type>::template getItem<FirstT, OtherT...>( *this );
218 }
219 
220 template <class FirstT, class ... OtherT>
221 template <size_t Index> inline
222 auto GenericBag<FirstT, OtherT...>::get() const -> typename getIndexType<Index, GenericBag>::type const &
223 {
224  return getIndexFromBag<Index, typename getIndexType<Index, GenericBag>::type>::template getItem<FirstT, OtherT...>( *this );
225 }
226 
227 template <class FirstT, class ... OtherT>
228 template <class T> inline
229 auto GenericBag<FirstT, OtherT...>::tryGet() -> typename getReferenceType<T, FirstT, OtherT...>::type
230 {
231  return tryGetClassFromBag<height, typename getReferenceType<T, FirstT, OtherT...>::type, typename std::decay<T>::type, typename std::decay<FirstT>::type>::getItem( *this );
232 }
233 
234 template <class FirstT, class ... OtherT>
235 template <class T> inline
236 typename std::decay<T>::type const & GenericBag<FirstT, OtherT...>::tryGet() const
237 {
238  return tryGetClassFromBag<height, typename std::decay<T>::type const &, typename std::decay<T>::type, typename std::decay<FirstT>::type>::getItem( *this );
239 }
240 
241 template <class FirstT, class ... OtherT>
242 template <class T> inline
244 {
245  try
246  {
247  tryGetClassFromBag<height, T, typename std::decay<T>::type, typename std::decay<FirstT>::type>::getItem( *this );
248  return true;
249  }
251  {
252  return false;
253  }
254 }
255 
256 template <class FirstT, class ... OtherT> inline
258 {
259  return itsFirst;
260 }
261 
262 template <class FirstT, class ... OtherT> inline
263 FirstT const & GenericBag<FirstT, OtherT...>::first() const
264 {
265  return itsFirst;
266 }
267 
268 template <class FirstT, class ... OtherT> inline
269 GenericBag<OtherT...> & GenericBag<FirstT, OtherT...>::other()
270 {
271  return *this;
272 }
273 
274 template <class FirstT, class ... OtherT> inline
275 GenericBag<OtherT...> const & GenericBag<FirstT, OtherT...>::other() const
276 {
277  return *this;
278 }
279 
280 //#########################################################################
281 //# copy Initialize
282 //#########################################################################
283 template <class RetT, bool Reference>
284 struct copyInitialize<true, Reference, RetT>
285 {
286  template <class BagType>
287  inline static RetT
288  getItem( BagType && bag )
289  {
290  // This const_cast is necessary since we when we copy construct, we mark the
291  // item to copy as a const &, which automatically makes all access to its members const.
292  // However, the types it holds may not actually be const. RetT will have already figured out
293  // whether the returned reference should actually be const or not, so we'll use it to strip out
294  // any superflous const introduced by the const accessor of get()
295  return const_cast<RetT>( bag.template get<RetT>() );
296  }
297 };
298 
299 template <class RetT>
300 struct copyInitialize<false, false, RetT>
301 {
302  template <class BagType>
303  inline static RetT
304  getItem( BagType && bag )
305  {
306  return RetT();
307  }
308 };
309 
310 template <class RetT>
311 struct copyInitialize<false, true, RetT>
312 {
313  template <class BagType>
314  inline static RetT
315  getItem( BagType && bag )
316  {
317  // We want this error to pop up anytime this function gets instantiated, but not when it is parsed in general,
318  // so we use the sizeof... on a template parameter that we know will always fail, but not fail until this is
319  // instantiated
320  static_assert( sizeof(BagType) < 0, "Could not find a match to initialize reference" );
321  return RetT();
322  }
323 };
324 
325 //#########################################################################
326 //# Type finder
327 //#########################################################################
328 // no match not end of the line case
329 template <class DecayedT1, class DecayedT2, class FirstT, class ... OtherT>
330 struct getReferenceTypeImpl<DecayedT1, DecayedT2, FirstT, OtherT...>
331 {
332  typedef typename getReferenceTypeImpl<DecayedT1, typename std::decay<typename GenericBag<OtherT...>::FirstType>::type,
333  OtherT...>::type type;
334 };
335 
336 // matching case
337 template <class DecayedT, class FirstT, class ... OtherT>
338 struct getReferenceTypeImpl<DecayedT, DecayedT, FirstT, OtherT...>
339 {
340  typedef typename std::conditional<
341  std::is_const<typename std::remove_reference<FirstT>::type>::value, // The remove ref is necessary so we can correctly identify T const & as a ref to something const
342  typename std::add_lvalue_reference<typename std::add_const<typename std::decay<FirstT>::type>::type>::type,
343  typename std::add_lvalue_reference<typename std::decay<FirstT>::type>::type>::type type;
344 };
345 
346 // no match case
347 template <class DecayedT1, class DecayedT2>
348 struct getReferenceTypeImpl<DecayedT1, DecayedT2>
349 {
350  typedef DecayedT1 type;
351 };
352 
353 //#########################################################################
354 //# Inner Search
355 //#########################################################################
356 
357 // non matching case
358 template <size_t height, class DesiredT,
359  class DecayedT1, class DecayedT2>
360 struct bagInnerSearch
361 {
362  template <class T2, class ... OtherT2>
363  inline static void search( DesiredT & t, GenericBag<T2, OtherT2...> const & other )
364  {
365  bagInnerSearch<height - 1, DesiredT,
366  DecayedT1, typename std::decay<typename GenericBag<OtherT2...>::FirstType>::type>::template
367  search( t, other.other() );
368  }
369 };
370 
371 // matching case
372 template <size_t height, class DesiredT,
373  class DecayedT>
374 struct bagInnerSearch<height, DesiredT, DecayedT, DecayedT>
375 {
376  template <class T2, class ... OtherT2>
377  inline static void search( DesiredT & t, GenericBag<T2, OtherT2...> const & other )
378  {
379  t = other.first();
380  }
381 };
382 
383 // no match all out case
384 template <class DesiredT,
385  class DecayedT1, class DecayedT2>
386 struct bagInnerSearch<0, DesiredT, DecayedT1, DecayedT2>
387 {
388  template <class ... Args>
389  inline static void search( DesiredT & t, GenericBag<Args...> const & other )
390  {
391  return;
392  }
393 };
394 
395 //#########################################################################
396 //# Outer Search
397 //#########################################################################
398 
399 // Outer search non base case
400 template <size_t height1, size_t height2, class FirstT2, class ... OtherT2>
401 struct bagOuterSearch
402 {
403  template <class FirstT1, class ... OtherT1>
404  inline static void search( GenericBag<FirstT1, OtherT1...> & bag1, GenericBag<FirstT2, OtherT2...> const & bag2 )
405  {
406  // Do an inner search against bag2
407  bagInnerSearch<height2, FirstT1, typename std::decay<FirstT1>::type, typename std::decay<FirstT2>::type>::template search( bag1.first(), bag2 );
408 
409  // Recurse to next item in bag1
410  bagOuterSearch<height1 - 1, height2, FirstT2, OtherT2...>::template search( bag1.other(), bag2 );
411  }
412 }; // bagOuterSearch
413 
414 // Outer search base case
415 template <size_t height2, class FirstT2, class ... OtherT2>
416 struct bagOuterSearch<0, height2, FirstT2, OtherT2...>
417 {
418  template <class ... Args>
419  inline static void search( GenericBag<Args...> & bag1, GenericBag<OtherT2...> const & bag2 )
420  {
421  return;
422  }
423 }; // bagOuterSearch
424 
425 //#########################################################################
426 //# Inner Search Move
427 //#########################################################################
428 
429 // non matching case
430 template <size_t height, class DesiredT,
431  class DecayedT1, class DecayedT2>
432 struct bagInnerSearchMove
433 {
434  template <class T2, class ... OtherT2>
435  inline static void search( DesiredT & t, GenericBag<T2, OtherT2...> && other )
436  {
437  bagInnerSearchMove<height - 1, DesiredT,
438  DecayedT1, typename std::decay<typename GenericBag<OtherT2...>::FirstType>::type>::template
439  search( t, std::forward<GenericBag<OtherT2...>>( other.other() ) );
440  }
441 };
442 
443 // matching case
444 template <size_t height, class DesiredT,
445  class DecayedT>
446 struct bagInnerSearchMove<height, DesiredT, DecayedT, DecayedT>
447 {
448  template <class T2, class ... OtherT2>
449  inline static void search( DesiredT & t, GenericBag<T2, OtherT2...> && other )
450  {
451  t = std::move( other.first() );
452  }
453 };
454 
455 // no match all out case
456 template <class DesiredT,
457  class DecayedT1, class DecayedT2>
458 struct bagInnerSearchMove<0, DesiredT, DecayedT1, DecayedT2>
459 {
460  template <class ... Args>
461  inline static void search( DesiredT & t, GenericBag<Args...> && other )
462  {
463  return;
464  }
465 };
466 
467 //#########################################################################
468 //# Outer Search Move
469 //#########################################################################
470 
471 // Outer search non base case
472 // this is for move construction
473 template <size_t height1, size_t height2, class FirstT2, class ... OtherT2>
474 struct bagOuterSearchMove
475 {
476  template <class FirstT1, class ... OtherT1>
477  inline static void search( GenericBag<FirstT1, OtherT1...> & bag1, GenericBag<FirstT2, OtherT2...> && bag2 )
478  {
479  // Do an inner search against bag2
480  bagInnerSearchMove<height2, FirstT1, typename std::decay<FirstT1>::type, typename std::decay<FirstT2>::type>::template search(
481  bag1.first(), std::forward<GenericBag<FirstT2, OtherT2...>>( bag2 ) );
482 
483  // Recurse to next item in bag1
484  bagOuterSearchMove<height1 - 1, height2, FirstT2, OtherT2...>::template
485  search( bag1.other(), std::forward<GenericBag<FirstT2, OtherT2...>>( bag2 ) );
486  }
487 }; // bagOuterSearch
488 
489 // Outer search base case
490 // this is for move consturction
491 template <size_t height2, class FirstT2, class ... OtherT2>
492 struct bagOuterSearchMove<0, height2, FirstT2, OtherT2...>
493 {
494  template <class ... Args>
495  inline static void search( GenericBag<Args...> & bag1, GenericBag<FirstT2, OtherT2...> && bag2 )
496  {
497  return;
498  }
499 }; // bagOuterSearch
500 
501 //#########################################################################
502 //# get Class from Bag
503 //#########################################################################
504 
505 template <size_t height, class RetT, class DecayedT1, class DecayedT2>
506 struct getClassFromBag
507 {
508  template <class FirstT, class ... OtherT>
509  inline static RetT
510  getItem( GenericBag<FirstT, OtherT...> & bag )
511  {
512  return getClassFromBag<height - 1, RetT, DecayedT1, typename std::decay<typename GenericBag<OtherT...>::FirstType>::type>::template
513  getItem( bag.other() );
514  static_assert( !std::is_same<GenericBag<OtherT...>, GenericBag<>>::value, "Requested class not contained in bag" );
515  }
516 
517  template <class FirstT, class ... OtherT>
518  inline static RetT const
519  getItem( GenericBag<FirstT, OtherT...> const & bag )
520  {
521  return getClassFromBag<height - 1, RetT, DecayedT1, typename std::decay<typename GenericBag<OtherT...>::FirstType>::type>::template
522  getItem( bag.other() );
523  static_assert( !std::is_same<GenericBag<OtherT...>, GenericBag<>>::value, "Requested class not contained in bag" );
524  }
525 }; // getClassFromBag
526 
527 template <size_t height, class RetT, class DecayedT>
528 struct getClassFromBag<height, RetT, DecayedT, DecayedT>
529 {
530  template <class ... Args>
531  inline static RetT
532  getItem( GenericBag<Args...> & bag )
533  {
534  return bag.first();
535  }
536 
537  template <class ... Args>
538  inline static RetT const
539  getItem( GenericBag<Args...> const & bag )
540  {
541  return bag.first();
542  }
543 }; // getClassFromBag
544 
545 //#########################################################################
546 //# try getClassFromBag
547 //#########################################################################
548 
549 // Alternate version of getClassFromBag which throws when it cannot find a match
550 template <size_t height, class RetT, class DecayedT1, class DecayedT2>
551 struct tryGetClassFromBag
552 {
553  template <class FirstT, class ... OtherT>
554  inline static RetT
555  getItem( GenericBag<FirstT, OtherT...> & bag )
556  {
557  return tryGetClassFromBag<height - 1, RetT, DecayedT1, typename std::decay<typename GenericBag<OtherT...>::FirstType>::type>::template
558  getItem( bag.other() );
559  }
560 
561  template <class FirstT, class ... OtherT>
562  inline static RetT const
563  getItem( GenericBag<FirstT, OtherT...> const & bag )
564  {
565  return tryGetClassFromBag<height - 1, RetT, DecayedT1, typename std::decay<typename GenericBag<OtherT...>::FirstType>::type>::template
566  getItem( bag.other() );
567  }
568 /*
569  inline static RetT
570  getItem( GenericBag<> & bag )
571  {
572  throw nrt::exception::GenericBagException( demangledName<RetT>() );
573  }
574 
575  inline static RetT const
576  getItem( GenericBag<> const & bag )
577  {
578  throw nrt::exception::GenericBagException( demangledName<RetT>() );
579  }
580 */
581 }; // tryGetClassFromBag
582 
583 template <class RetT, class DecayedT1, class DecayedT2>
584 struct tryGetClassFromBag<0, RetT, DecayedT1, DecayedT2>
585 {
586  template <class ... Args>
587  inline static RetT
588  getItem( GenericBag<Args...> & bag )
589  {
590  throw nrt::exception::GenericBagException( demangledName<RetT>() );
591  }
592 
593  template <class ... Args>
594  inline static RetT const
595  getItem( GenericBag<Args...> const & bag )
596  {
597  throw nrt::exception::GenericBagException( demangledName<RetT>() );
598  }
599 };
600 
601 // catch a match
602 template <size_t height, class RetT, class DecayedT>
603 struct tryGetClassFromBag<height, RetT, DecayedT, DecayedT>
604 {
605  template <class ... Args>
606  inline static RetT
607  getItem( GenericBag<Args...> & bag )
608  {
609  return bag.first();
610  }
611 
612  template <class ... Args>
613  inline static RetT const
614  getItem( GenericBag<Args...> const & bag )
615  {
616  return bag.first();
617  }
618 }; // tryGetClassFromBag
619 
620 //#########################################################################
621 //# getIndexFromBag
622 //#########################################################################
623 
624 template <size_t Index, class RetT>
625 struct getIndexFromBag
626 {
627  template <class FirstT, class ... OtherT>
628  inline static RetT &
629  getItem( GenericBag<FirstT, OtherT...> & bag )
630  {
631  return getIndexFromBag<Index - 1, RetT>::template getItem( bag.other() );
632  }
633 
634  template <class FirstT, class ... OtherT>
635  inline static RetT const &
636  getItem( GenericBag<FirstT, OtherT...> const & bag )
637  {
638  return getIndexFromBag<Index - 1, RetT>::template getItem( bag.other() );
639  }
640 }; // getIndexFromBag normal case
641 
642 template <class RetT>
643 struct getIndexFromBag<0, RetT>
644 {
645  template <class FirstT, class ... OtherT>
646  inline static RetT &
647  getItem( GenericBag<FirstT, OtherT...> & bag )
648  {
649  return bag.first();
650  }
651 
652  template <class FirstT, class ... OtherT>
653  inline static RetT const &
654  getItem( GenericBag<FirstT, OtherT...> const & bag )
655  {
656  return bag.first();
657  }
658 }; //getIndexFromBag base case
659 
660 //#########################################################################
661 //# expandAndApply
662 //#########################################################################
663 
664 // normal case
665 template <size_t Height, class Functor, class RetType>
666 struct expandAndApply
667 {
668  template <class FirstT, class ... OtherT, class ... Args>
669  inline static RetType
670  apply( Functor && f, GenericBag<FirstT, OtherT...> const & bag, Args && ... args )
671  {
672  return expandAndApply<Height - 1, Functor, RetType>::apply( std::forward<Functor>( f ), bag.other(), std::forward<Args>( args )..., f( bag.first() ) );
673  }
674 };
675 
676 // normal case specialized for no return
677 template <size_t Height, class Functor>
678 struct expandAndApply<Height, Functor, void>
679 {
680  template <class FirstT, class ... OtherT>
681  inline static void
682  apply( Functor && f, GenericBag<FirstT, OtherT...> & bag )
683  {
684  f( bag.first() );
685  expandAndApply<Height - 1, Functor, void>::apply( std::forward<Functor>( f ), bag.other() );
686  }
687 };
688 
689 // base case, actually build the return value
690 template <class Functor, class RetType>
691 struct expandAndApply<0, Functor, RetType>
692 {
693  template <class ... Args>
694  inline static RetType
695  apply( Functor && f, GenericBag<> const & bag, Args && ... args )
696  {
697  return RetType( std::forward<Args>( args )... );
698  }
699 };
700 
701 // normal case specialized for no return, base case
702 template <class Functor>
703 struct expandAndApply<0, Functor, void>
704 {
705  inline static void
706  apply( Functor && f, GenericBag<> & bag )
707  {
708  return;
709  }
710 };
711 
712 //#########################################################################
713 // StreamableGenericBag
714 //#########################################################################
715 
716 struct initiateGenericBagStream
717 {
718  template <class ... Args>
719  inline static std::ostream & outputItem( std::ostream & out, StreamableGenericBag<Args...> const & bag )
720  {
721  return streamGenericBagContents<StreamableGenericBag<Args...>::height>::template outputItem( out, bag );
722  }
723 
724  inline static std::ostream & outputItem( std::ostream & out, StreamableGenericBag<> const & bag )
725  { return out; }
726 
727  template <class ... Args>
728  inline static void inputItem( std::vector<std::string> & in, StreamableGenericBag<Args...> & bag )
729  {
730  streamGenericBagContents<StreamableGenericBag<Args...>::height>::template inputItem( in, bag );
731  }
732 
733  inline static void inputItem( std::vector<std::string> & in, StreamableGenericBag<> & bag )
734  { return; }
735 };
736 
737 template <class FirstT, class ... OtherT> inline
738 StreamableGenericBag<FirstT, OtherT...>::StreamableGenericBag() : GenericBag<FirstT, OtherT...>()
739 { }
740 
741 template <class FirstT, class ... OtherT> inline
742 StreamableGenericBag<FirstT, OtherT...>::StreamableGenericBag( FirstT const & first, OtherT const & ... other ) :
743  GenericBag<FirstT, OtherT...>( first, other... )
744 { }
745 
746 template <class FirstT, class ... OtherT>
747 template <class ... Types> inline
748 StreamableGenericBag<FirstT, OtherT...>::StreamableGenericBag( GenericBag<Types...> const & other )
749  : GenericBag<FirstT, OtherT...>( other )
750 { }
751 
752 template <class FirstT, class ... OtherT>
753 template <class ... Types> inline
754 StreamableGenericBag<FirstT, OtherT...>::StreamableGenericBag( StreamableGenericBag<Types...> const & other )
755  : GenericBag<FirstT, OtherT...>( other )
756 { }
757 
758 template <class FirstT, class ... OtherT>
759 template <class ... Types> inline
761  : GenericBag<FirstT, OtherT...>( other )
762 { }
763 
764 template <class FirstT, class ... OtherT>
765 template <class ... Types> inline
766 StreamableGenericBag<FirstT, OtherT...>::StreamableGenericBag( StreamableGenericBag<Types...> && other )
767  : GenericBag<FirstT, OtherT...>( other )
768 { }
769 
770 template <class ... Args> inline
771 std::istream& operator>>( std::istream & in, StreamableGenericBag<Args...> & bag )
772 {
773  // split by our delimiter, reverse (so we can just drop the tail each recursion)
774  std::string stringRep;
775  std::getline( in, stringRep );
776  std::vector<std::string> splitVec = nrt::splitString(stringRep, ';');
777  std::reverse( splitVec.begin(), splitVec.end() );
778 
779  initiateGenericBagStream::template inputItem( splitVec, bag );
780 
781  return in;
782 }
783 
784 template <class ... Args> inline
785 std::ostream& operator<<( std::ostream & out, StreamableGenericBag<Args...> const & bag )
786 {
787  return initiateGenericBagStream::template outputItem( out, bag );
788 }
789 
790 template <size_t height>
791 struct streamGenericBagContents
792 {
793  template <class BagT>
794  inline static std::ostream &
795  outputItem( std::ostream & out, BagT const & bag )
796  {
797  out << bag.first();
798 
799  if( height > 1 )
800  out << "; ";
801 
802  return streamGenericBagContents<height - 1>::template outputItem( out, bag.other() );
803  }
804 
805  template <class BagT>
806  inline static void
807  inputItem( std::vector<std::string> & in, BagT & bag )
808  {
809  std::istringstream current( in.back() );
810  current >> bag.first();
811  in.pop_back();
812 
813  streamGenericBagContents<height - 1>::template inputItem( in, bag.other() );
814  }
815 };
816 
817 template <>
818 struct streamGenericBagContents<0>
819 {
820  template <class BagT>
821  inline static std::ostream &
822  outputItem( std::ostream & out, BagT const & bag )
823  {
824  return out;
825  }
826 
827  template <class BagT>
828  inline static void
829  inputItem( std::vector<std::string> & in, BagT & bag )
830  {
831  return;
832  }
833 }; // streamGenericBagContents
834 
835 #endif // INCLUDE_NRT_CORE_DESIGN_DETAILS_GENERICBAGIMPL_H