RefleX
Build DDS Applications in Modern C++ without IDL
 All Classes Namespaces Files Functions Variables Typedefs Enumerator Friends Macros Pages
tuple_iterator.h
Go to the documentation of this file.
1 /*********************************************************************************************
2 (c) 2005-2014 Copyright, Real-Time Innovations, Inc. All rights reserved.
3 RTI grants Licensee a license to use, modify, compile, and create derivative works
4 of the Software. Licensee has the right to distribute object form only for use with RTI
5 products. The Software is provided "as is", with no warranty of any type, including
6 any warranty for fitness for any purpose. RTI is under no obligation to maintain or
7 support the Software. RTI shall not be liable for any incidental or consequential
8 damages arising out of the use or inability to use the software.
9 **********************************************************************************************/
10 
11 #ifndef RTIREFLEX_TUPLE_ITERATOR_H
12 #define RTIREFLEX_TUPLE_ITERATOR_H
13 
14 #include <iostream>
15 #include <type_traits>
16 #include <sstream>
17 
18 #include <ndds/ndds_cpp.h>
19 
20 #include "reflex/member_names.h"
21 #include "reflex/disc_union.h"
22 #include "reflex/enable_if.h"
23 
24 #define UNUSED_VAR(i) do { (void)(i); } while (0)
25 
26 namespace reflex {
27 
28  namespace detail {
29 
30  template <class T>
31  void set_member_forward(
32  DDS_DynamicData & instance,
33  const MemberAccess &ma,
34  const T & val);
35 
36  template <class T>
37  void get_member_forward(
38  const DDS_DynamicData & instance,
39  const MemberAccess &ma,
40  T & val);
41 
42  template <class T>
43  void add_member_forward(
44  DDS_TypeCodeFactory * factory,
45  DDS_TypeCode * outerTc,
46  const char * member_name,
47  unsigned char flags,
48  int id,
49  const T *tptr);
50 
51  template <class Case>
52  void case_add_forward(
53  DDS_TypeCodeFactory * factory,
54  const char * member_name,
55  DDS_UnionMember & umember);
56 
57  template <class T>
58  void deleteTc_forward(
59  DDS_TypeCodeFactory * factory,
60  DDS_TypeCode * tc);
61 
62  template <class Typelist,
63  unsigned int I,
64  class TUnion>
65  bool get_union_case(
66  const DDS_DynamicData &instance,
67  const MemberAccess & ma,
68  int discriminator_value,
69  TUnion& val)
70  {
71  typedef typename reflex::meta::at<Typelist, I>::type CaseI;
72  if (CaseI::matches(discriminator_value))
73  {
74  typename CaseI::type * data_ptr = reflex::meta::get<I>(val.get_caseptr_tuple());
75  bool data_in_case_ptr = data_ptr ? true : false;
76 
77  if (data_in_case_ptr == false)
78  {
79  // variant may be empty. So inittialize it first.
80  // Otherwise, we will get boost::bad_get exception.
81  // Ideally, like boost.optinal we want support for
82  // typed_in_place_factory in boost.variant.
83  // but boost.variant does not support it. Sigh!
84  // val.get_variant() = boost::in_place<typename CaseI::type>();
85 
86  val.get_variant() = CaseI(); // default c-tor
87  data_ptr = &(boost::get<CaseI>(val.get_variant()).get());
88  }
89 
90  if (ma.access_by_id())
91  get_member_forward(
92  instance,
93  MemberAccess::BY_ID(discriminator_value),
94  *data_ptr);
95  else
96  {
99  I>::member_info();
100 
101  get_member_forward(
102  instance,
103  MemberAccess::BY_NAME(info.name.c_str()),
104  *data_ptr);
105  }
106  if (data_in_case_ptr)
107  val.set_active_index(I);
108 
109  return true;
110  }
111  return false;
112  }
113 
114  template <class Typelist,
115  unsigned int I,
116  class TUnion>
117  bool set_union_case(
118  DDS_DynamicData &instance,
119  const MemberAccess & ma,
120  const TUnion& val)
121  {
122  // Note that CaseTypelist is off by one w.r.t the variant.
123  if ((I == val.get_active_index()) ||
124  (I == val.get_variant().which() - 1))
125  {
126  typedef typename reflex::meta::at<Typelist, I>::type CaseI;
127  typename CaseI::type const * data_ptr =
128  reflex::meta::get<I>(val.get_caseptr_tuple()) ? :
129  &(boost::get<CaseI>(val.get_variant()).get());
130 
131  if (ma.access_by_id())
132  set_member_forward(
133  instance,
134  MemberAccess::BY_ID(CaseI::discriminator),
135  *data_ptr);
136  else
137  {
140  I>::member_info();
141 
142  set_member_forward(
143  instance,
144  MemberAccess::BY_NAME(info.name.c_str()),
145  *data_ptr);
146  }
147 
148  return true;
149  }
150  return false;
151  }
152 
153  template <class Typelist,
154  unsigned int I,
155  unsigned int MAX_INDEX>
156  struct TypelistIterator
157  {
158  typedef TypelistIterator<
159  Typelist,
160  I + 1,
161  MAX_INDEX> Next;
162 
163  static void set(
164  DDS_DynamicData & instance,
165  const MemberAccess &ma,
166  const Typelist & tuple)
167  {
168 #ifdef REFLEX_DEBUG
169  unsigned i = I;
170  UNUSED_VAR(i);
171  std::string member_name =
173 #endif
174 
175  if (ma.access_by_id())
176  {
177  set_member_forward(instance, ma, reflex::meta::get<I>(tuple));
178  Next::set(instance, ma + 1, tuple);
179  }
180  else
181  {
184 
185  set_member_forward(
186  instance,
187  MemberAccess::BY_NAME(info.name.c_str()),
188  reflex::meta::get<I>(tuple));
189 
190  Next::set(instance, ma, tuple);
191  }
192  }
193 
194  static void get(
195  const DDS_DynamicData & instance,
196  const MemberAccess &ma,
197  Typelist & tuple)
198  {
199 #ifdef REFLEX_DEBUG
200  unsigned i = I;
201  UNUSED_VAR(i);
202  std::string member_name =
204 #endif
205  if (ma.access_by_id())
206  {
207  get_member_forward(instance, ma, reflex::meta::get<I>(tuple));
208  Next::get(instance, ma + 1, tuple);
209  }
210  else
211  {
214  I>::member_info();
215 
216  get_member_forward(
217  instance,
218  MemberAccess::BY_NAME(info.name.c_str()),
219  reflex::meta::get<I>(tuple));
220  Next::get(instance, ma, tuple);
221  }
222  }
223 
224  static void add(
225  DDS_TypeCodeFactory * factory,
226  DDS_TypeCode * outer_structTc)
227  {
228 #ifdef REFLEX_DEBUG
229  unsigned i = I;
230  UNUSED_VAR(i);
231  std::string member_name =
233 #endif
234 
235  typedef typename reflex::meta::at<Typelist, I>::type Inner;
236  typedef typename reflex::meta::remove_reference<Inner>::type InnerNoRef;
237 
240  I
241  >::member_info();
242 
243  add_member_forward(factory,
244  outer_structTc,
245  info.name.c_str(),
246  info.value,
247  I + 1,
248  static_cast<InnerNoRef *>(0));
249 
250  Next::add(factory, outer_structTc);
251  }
252 
253  static void add_union_member(
254  DDS_TypeCodeFactory * factory,
255  DDS_UnionMemberSeq & seq)
256  {
257  typedef typename reflex::meta::at<Typelist, I>::type CaseI;
258 
261  I
262  >::member_info();
263 
264  case_add_forward<CaseI>(factory, info.name.c_str(), seq[I]);
265 
266  Next::add_union_member(factory, seq);
267  }
268 
269  static void delete_typecodes(
270  DDS_TypeCodeFactory * factory,
271  DDS_UnionMemberSeq & seq)
272  {
273  typedef typename reflex::meta::at<Typelist, I>::type Case;
274  typedef typename reflex::meta::remove_reference<typename Case::type>::type CaseTypeNoRef;
275  deleteTc_forward<CaseTypeNoRef>(
276  factory,
277  const_cast<DDS_TypeCode *>(seq[I].type));
278  Next::delete_typecodes(factory, seq);
279  }
280 
281  template <class TUnion>
282  static void set_union(
283  DDS_DynamicData &instance,
284  const MemberAccess & ma,
285  const TUnion& val)
286  {
287  if (!set_union_case<Typelist, I>(instance, ma, val))
288  Next::set_union(instance, ma, val);
289  }
290 
291  template <class TUnion>
292  static void get_union(
293  const DDS_DynamicData &instance,
294  const MemberAccess & ma,
295  int discriminator_value,
296  TUnion& val)
297  {
298  if (!get_union_case<Typelist, I>(instance, ma, discriminator_value, val))
299  Next::get_union(instance, ma, discriminator_value, val);
300  }
301  };
302 
303  template <class Typelist,
304  unsigned int MAX_INDEX>
305  struct TypelistIterator<Typelist, MAX_INDEX, MAX_INDEX>
306  {
307  static void set(
308  DDS_DynamicData & instance,
309  const MemberAccess &ma,
310  const Typelist & tuple)
311  {
312 #ifdef REFLEX_DEBUG
313  unsigned max = MAX_INDEX;
314  UNUSED_VAR(max);
315  std::string member_name =
317 #endif
318 
319  if (ma.access_by_id())
320  {
321  set_member_forward(instance, ma, reflex::meta::get<MAX_INDEX>(tuple));
322  }
323  else
324  {
327  MAX_INDEX>::member_info();
328 
329  set_member_forward(
330  instance,
331  MemberAccess::BY_NAME(info.name.c_str()),
332  reflex::meta::get<MAX_INDEX>(tuple));
333  }
334  }
335 
336  static void get(const DDS_DynamicData & instance,
337  const MemberAccess &ma,
338  Typelist & tuple)
339  {
340 #ifdef REFLEX_DEBUG
341  unsigned max = MAX_INDEX;
342  UNUSED_VAR(max);
343  std::string member_name =
345 #endif
346 
347  if (ma.access_by_id())
348  {
349  get_member_forward(instance, ma, reflex::meta::get<MAX_INDEX>(tuple));
350  }
351  else
352  {
355  MAX_INDEX>::member_info();
356 
357  get_member_forward(
358  instance,
359  MemberAccess::BY_NAME(info.name.c_str()),
360  reflex::meta::get<MAX_INDEX>(tuple));
361  }
362  }
363 
364  static void add(
365  DDS_TypeCodeFactory * factory,
366  DDS_TypeCode * outer_structTc)
367  {
368 #ifdef REFLEX_DEBUG
369  unsigned max = MAX_INDEX;
370  UNUSED_VAR(max);
371  std::string member_name =
373 #endif
374 
375  typedef typename reflex::meta::at<Typelist, MAX_INDEX>::type Inner;
376  typedef typename reflex::meta::remove_reference<Inner>::type InnerNoRef;
377 
380  MAX_INDEX>::member_info();
381 
382  add_member_forward(factory,
383  outer_structTc,
384  info.name.c_str(),
385  info.value,
386  MAX_INDEX + 1,
387  static_cast<InnerNoRef *>(0));
388  }
389 
390  static void add_union_member(
391  DDS_TypeCodeFactory * factory,
392  DDS_UnionMemberSeq & seq)
393  {
394  typedef typename reflex::meta::at<Typelist, MAX_INDEX>::type CaseI;
397  MAX_INDEX>::member_info();
398 
399  case_add_forward<CaseI>(factory, info.name.c_str(), seq[MAX_INDEX]);
400  }
401 
402  static void delete_typecodes(
403  DDS_TypeCodeFactory * factory,
404  DDS_UnionMemberSeq & seq)
405  {
406  typedef typename reflex::meta::at<Typelist, MAX_INDEX>::type Case;
407  typedef typename reflex::meta::remove_reference<typename Case::type>::type CaseTypeNoRef;
408  deleteTc_forward<CaseTypeNoRef>(
409  factory,
410  const_cast<DDS_TypeCode *>(seq[MAX_INDEX].type));
411  }
412 
413  template <class TUnion>
414  static void set_union(
415  DDS_DynamicData &instance,
416  const MemberAccess & ma,
417  const TUnion& val)
418  {
419  if (!set_union_case<Typelist, MAX_INDEX>(instance, ma, val))
420  {
421  throw std::runtime_error("set_union: Union was empty");
422  }
423  }
424 
425  template <class TUnion>
426  static void get_union(
427  const DDS_DynamicData &instance,
428  const MemberAccess & ma,
429  int discriminator_value,
430  TUnion& val)
431  {
432  if (!get_union_case<Typelist, MAX_INDEX>(
433  instance,
434  ma,
435  discriminator_value,
436  val))
437  {
438  std::stringstream stream;
439  stream << "get_union: No match for the discriminator. "
440  << "Did you forget to set a union member? "
441  << "Discriminator value = "
442  << discriminator_value;
443  throw std::runtime_error(stream.str());
444  }
445  }
446  };
447 
448  } // namespace detail
449 
450 } // namespace reflex
451 
452 #endif // RTIREFLEX_TUPLE_ITERATOR_H
453 
std::string name
Definition: member_names.h:49
unsigned char value
Definition: member_names.h:50
disable_if_lazy< reflex::type_traits::is_tuple< FusionSeq >::value, at< FusionSeq, I > >::type get(FusionSeq &seq)
Definition: enable_if.h:714
Definition: member_names.h:47
static MemberInfo member_info()
Definition: member_names.h:76
#define UNUSED_VAR(i)
Definition: tuple_iterator.h:24
T type
Definition: enable_if.h:571
boost::fusion::result_of::at_c< FusionSeq, I >::type type
Definition: enable_if.h:642
Definition: member_names.h:74