All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Macros Pages
components.hpp
Go to the documentation of this file.
1 //=======================================================================
2 // Copyright (c) 2013 Piotr Wygocki
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See
5 // accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 //=======================================================================
15 #ifndef PAAL_COMPONENTS_HPP
16 #define PAAL_COMPONENTS_HPP
17 
19 
20 #include <utility>
21 #include <iostream>
22 
23 namespace paal {
24 namespace data_structures {
25 
33 template <typename Name, typename Default> struct NameWithDefault;
34 
39 struct copy_tag {};
40 
41 // This namespace block contains implementation of the main class
42 // components<Names,Types> and needed meta functions
43 namespace detail {
44 
46 template <typename T> struct wrap_to_constructable {
47  typedef T type;
48 };
49 
50 
52 template <typename Name, typename Names, typename Types> struct type_for_name {
53  typedef typename remove_n_first<1, Names>::type NewNames;
54  typedef typename remove_n_first<1, Types>::type NewTypes;
55  typedef typename type_for_name<Name, NewNames, NewTypes>::type type;
56 };
57 
59 template <typename Name, typename Type, typename... NamesRest,
60  typename... TypesRest>
61 struct type_for_name<Name, TypesVector<Name, NamesRest...>,
62  TypesVector<Type, TypesRest...>> {
63  typedef Type type;
64 };
65 
66 
68 template <typename T, typename Name> class has_template_get {
69  private:
77  template <typename C>
78  static char f(wrap_to_constructable<decltype(
79  std::declval<const C>().template get<Name>())(C::*)() const> *);
80 
88  template <typename C> static long f(...);
89 
90  public:
95  static const bool value =
96  (sizeof(f<typename std::decay<T>::type>(nullptr)) == sizeof(char));
97 };
98 
102 struct movable_tag {};
106 struct Notmovable_tag {};
107 
108 // declaration of main class components
109 template <typename Names, typename Types> class components;
110 
111 // specialization for empty Names list
112 template <> class components<TypesVector<>, TypesVector<>> {
113  public:
114  void get() const;
115  void call() const;
116  void call2() const;
117 
118  template <typename... Unused> components(const Unused &...) {}
119 };
120 
121 // specialization for nonempty types list
122 // class keeps first component as data memer
123 // rest of the components are kept in superclass.
124 template <typename Name, typename Type, typename... NamesRest,
125  typename... TypesRest>
126 class components<TypesVector<Name, NamesRest...>,
127  TypesVector<Type, TypesRest...>> : public components<
128  TypesVector<NamesRest...>, TypesVector<TypesRest...>> {
129  typedef components<TypesVector<NamesRest...>, TypesVector<TypesRest...>>
130  base;
131  typedef TypesVector<Name, NamesRest...> Names;
132  typedef TypesVector<Type, TypesRest...> Types;
133 
135  template <typename ComponentName>
136  using is_my_name =
137  typename std::enable_if<std::is_same<ComponentName, Name>::value>::type;
138 
139  public:
140  using base::get;
141 
143  // we do not use = default, cause we'd like to value initialize POD's.
144  components() : base{}, m_component{} {};
145 
146  // copy constructor
147  components(components const & other)
148  : base(static_cast<base const &>(other)), m_component(other.get<Name>()) {}
149 
150  // doesn't work on clang 3.2 // change in the standard and visual studio 2015 preview
151  // components(components &) = default;
152  // constructor taking nonconst lvalue reference
153  components(components &other)
154  : base(static_cast<base &>(other)), m_component(other.get<Name>()) {}
155 
156  // move constructor
157  components(components &&) = default;
158 
159  // assignment operator
160  components &operator=(components const & other) {
161 
162  static_cast<base &>(*this) = static_cast<base &>(other);
163  m_component = other.get<Name>();
164  return *this;
165  }
166 
167  // doesn't work on clang 3.2 // change in the standard
168  // components& operator=(components &) = default;
169  // assignment operator taking nonconst lvalue reference
170  components &operator=(components &other) {
171  static_cast<base &>(*this) = static_cast<base &>(other);
172  m_component = other.get<Name>();
173  return *this;
174  }
175 
176  // default move operator
177  components &operator=(components &&) = default;
178 
190  template <typename T, typename... TypesPrefix>
191  components(T &&t, TypesPrefix &&... types)
192  : base(std::forward<TypesPrefix>(types)...),
193  m_component(std::forward<T>(t)) {}
194 
195  // copy constructor takes class wich has get<Name> member function
196  // the get<> function dosn't have to be available for all names.
197  // @param copy_tag is helps identify this constructor
198  template <typename Comps>
199  components(const Comps &comps, copy_tag)
200  : components(comps, Notmovable_tag()) {}
201 
202  // move constructor takes class wich has get<Name> member function
203  // the get<> function dosn't have to be available for all names.
204  // In this version each of the components taken from comps
205  // is going to be moved.
206  // @param copy_tag is helps identify this constructor
207  template <typename Comps>
208  components(Comps &&comps, copy_tag)
209  : components(comps, movable_tag()) {}
210 
220  template <typename ComponentName, typename = is_my_name<ComponentName>>
221  Type &get(wrap_to_constructable<Name> dummy =
223  return m_component;
224  }
225 
235  template <typename ComponentName, typename = is_my_name<ComponentName>>
236  const Type &get(wrap_to_constructable<Name> dummy =
237  wrap_to_constructable<Name>()) const {
238  return m_component;
239  }
240 
252  template <typename ComponentName, typename... Args>
253  auto call(Args &&... args)->decltype(std::declval<
254  typename type_for_name<ComponentName, Names, Types>::type>()(
255  std::forward<Args>(args)...)) {
256  return this->template get<ComponentName>()(std::forward<Args>(args)...);
257  }
258 
271  template <typename ComponentName, typename... Args>
272  auto call(Args &&... args) const->decltype(std::declval<
273  const typename type_for_name<ComponentName, Names, Types>::type>()(
274  std::forward<Args>(args)...)) {
275  return this->template get<ComponentName>()(std::forward<Args>(args)...);
276  }
277 
284  template <typename ComponentName>
285  void
286  set(const typename type_for_name<ComponentName, Names, Types>::type comp) {
287  this->get<ComponentName>() = std::move(comp);
288  }
289 
300  template <typename... NamesSubset, typename... SomeTypes>
302  // make(SomeTypes... types) {
303  // static_assert(sizeof...(NamesSubset) == sizeof...(SomeTypes),
304  // "Incorrect number of arguments.");
305  // return components<Names,
306  // Types>(components<TypesVector<NamesSubset...>,
307  // TypesVector<SomeTypes...>>(std::move(types)...), copy_tag());
308  make(SomeTypes &&... types) {
309  static_assert(sizeof...(NamesSubset) == sizeof...(SomeTypes),
310  "Incorrect number of arguments.");
311  components<TypesVector<NamesSubset...>, TypesVector<SomeTypes...>>
312  comps(std::forward<SomeTypes>(types)...);
313  return components<Names, Types>(std::move(comps), copy_tag());
314  }
315 
316  protected:
317 
318  // object is moved if move = true, otherwise passed by reference
319  template <bool move, typename A> A move_or_pass_reference(const A &a) {
320  return std::move(a);
321  }
322 
323  // const reference case
324  template <bool move, typename A,
325  typename = typename std::enable_if<!move>::type>
326  const A &move_or_pass_reference(const A &a) {
327  return a;
328  }
329 
330  // nonconst reference case
331  template <bool move, typename A,
332  typename = typename std::enable_if<!move>::type>
333  A &move_or_pass_reference(A &a) {
334  return a;
335  }
336 
337  // All of this constructor takes Comps as r-value reference,
338  // because they have to win specialization race with normal constructor.
339 
340  // case: movable object, has the appropriate get member function
341  template <typename Comps,
342  typename dummy = typename std::enable_if<
343  has_template_get<Comps, Name>::value, int>::type>
344  components(Comps &&comps, movable_tag m, dummy d = dummy())
345  : base(std::forward<Comps>(comps), std::move(m)),
346  // if Type is not reference type, comps.get<Name>() is moved otherwise
347  // reference is passed
348  m_component(
349  move_or_pass_reference<!std::is_lvalue_reference<Type>::value>(
350  comps.template get<Name>())) {}
351 
352  // case: movable object, does not have the appropriate get member function
353  template <typename Comps, typename dummy = typename std::enable_if<
354  !has_template_get<Comps, Name>::value>::type>
355  components(Comps &&comps, movable_tag m)
356  : base(std::forward<Comps>(comps), std::move(m)) {}
357 
358  // case: not movable object, has the appropriate get member function
359  template <typename Comps,
360  typename dummy = typename std::enable_if<
361  has_template_get<Comps, Name>::value, int>::type>
362  components(Comps &&comps, Notmovable_tag m, dummy d = dummy())
363  : base(std::forward<Comps>(comps), std::move(m)),
364  m_component(comps.template get<Name>()) {}
365 
366  // case: not movable object, does not have the appropriate get member
367  // function
368  template <typename Comps, typename dummy = typename std::enable_if<
369  !has_template_get<Comps, Name>::value>::type>
370  components(Comps &&comps, Notmovable_tag m)
371  : base(std::forward<Comps>(comps), std::move(m)) {}
372 
373  private:
374  Type m_component;
375 };
376 } // detail
377 
378 //This namespace contains class which sets all defaults and all needed meta functions.
379 
380 namespace detail {
381 
382 template <typename Names, typename Defaults, typename TypesPrefix>
384  static const int N = size<Names>::value;
385  static const int TYPES_NR = size<TypesPrefix>::value;
386  static_assert(TYPES_NR <= N, "Incrrect number of parameters");
387 
388  static const int DEFAULTS_NR = size<Defaults>::value;
389  static_assert(DEFAULTS_NR + TYPES_NR >= N, "Incrrect number of parameters");
390 
391  typedef typename remove_n_first<DEFAULTS_NR + TYPES_NR - N, Defaults>::type
392  NeededDefaults;
393 
394  typedef typename join<TypesPrefix, NeededDefaults>::type Types;
395 
396  public:
398 };
399 } // detail
400 
401 //Here are some meta functions, to parse the arguments
402 namespace detail {
409 template <typename T> struct get_name {
410  typedef T type;
411 };
412 
420 template <typename Name, typename Default>
421 struct get_name<NameWithDefault<Name, Default>> {
422  typedef Name type;
423 };
424 
430  template <typename Vector, typename NameWithDefault> struct apply {
431  typedef typename push_back<
432  Vector, typename get_name<NameWithDefault>::type>::type type;
433  };
434 };
435 
436 /*
437  * @brief Meta function takes NameWithDefault and Vector
438  * the result is new vector with new Name appended Default
439  */
441  // This case applies to when NameWithDefault is only name
442  template <typename Vector, typename Name> struct apply {
443  typedef Vector type;
444  };
445 
446  // This case applies when NameWithDefault contains Default
447  template <typename Vector, typename Name, typename Default>
448  struct apply<Vector, NameWithDefault<Name, Default>> {
449  typedef typename push_back<Vector, Default>::type type;
450  };
451 };
452 } // detail
453 
458 template <typename... ComponentNamesWithDefaults> class components {
459  typedef TypesVector<ComponentNamesWithDefaults...> NamesWithDefaults;
460 
462  typedef typename fold<NamesWithDefaults, TypesVector<>,
463  detail::push_back_name>::type Names;
464 
466  typedef typename fold<NamesWithDefaults, TypesVector<>,
467  detail::push_back_default>::type Defaults;
468 
474  template <class T> struct special_decay {
475  using type = typename std::decay<T>::type;
476  };
477 
483  template <class T> struct special_decay<std::reference_wrapper<T>> {
484  using type = T &;
485  };
486 
487  template <class T> using special_decay_t = typename special_decay<T>::type;
488 
489  public:
490  template <typename... ComponentTypes>
491  using type = typename detail::set_defaults<
492  Names, Defaults, TypesVector<ComponentTypes...>>::type;
493 
495  template <typename... components>
496  static type<special_decay_t<components>...>
498  return type<special_decay_t<components>...>(
499  std::forward<components>(comps)...);
500  }
501 
502  private:
503  // in this block we check if the defaults are on the last positions in the
504  // NamesWithDefaults
505  static const int N = size<NamesWithDefaults>::value;
506  static const int DEFAULTS_NR = size<Defaults>::value;
507  typedef typename remove_n_first<N - DEFAULTS_NR, NamesWithDefaults>::type
508  DefaultPart;
509  typedef typename fold<DefaultPart, TypesVector<>,
510  detail::push_back_default>::type DefaultsTest;
511  static_assert(std::is_same<DefaultsTest, Defaults>::value,
512  "Defaults values could be only on subsequent number of last "
513  "parameters");
514 };
515 
516 }
517 }
518 #endif // PAAL_COMPONENTS_HPP
Tag indicating that given object is movable.
Definition: components.hpp:102
static const bool value
tels if given type has get&lt;Name&gt;() memer function.
Definition: components.hpp:95
Standard fold function implementation.
Computes size of TypesVector.
static type< special_decay_t< components >...> make_components(components &&...comps)
make function for components
Definition: components.hpp:497
Tag indicating that given object is not movable.
Definition: components.hpp:106
static components< Names, Types > make(SomeTypes &&...types)
function creating components class, takes arguments only for assigned Names
Definition: components.hpp:308
This structure can be passed on Names list and represents Name and the default type value...
Definition: components.hpp:33
auto call(Args &&...args) const -> decltype(std::declval< const typename type_for_name< ComponentName, Names, Types >::type >()(std::forward< Args >(args)...))
This function directly calls component. m_component(args) has to be valid expresion const version...
Definition: components.hpp:272
If Name is kth on Names list, returns kth Type.
Definition: components.hpp:52
Meta function takes NameWithDefault and Vector the result is new vector with new Name appended Name...
Definition: components.hpp:429
get_name, gets name for either Name, or NamesWithDefaults struct this is the Name case ...
Definition: components.hpp:409
This is implementation of type vector taking advantage of variadic template. This implementation is N...
auto call(Args &&...args) -> decltype(std::declval< typename type_for_name< ComponentName, Names, Types >::type >()(std::forward< Args >(args)...))
This function directly calls component. m_component(args) has to be valid expresion nonconst version...
Definition: components.hpp:253
push back given val to TypesVector
Indicates that components constructor is in fact a Copy/Move Constructor.
Definition: components.hpp:39
removes first n elements from given TypesVector
void set(const typename type_for_name< ComponentName, Names, Types >::type comp)
setter for component assigned to Name.
Definition: components.hpp:286
components(T &&t, TypesPrefix &&...types)
constructor takes some number of arguments, This arguments has to be convertible to the same number o...
Definition: components.hpp:191
SFINAE check if the given type has get&lt;Name&gt;() member function.
Definition: components.hpp:68