OSVR-Core  0.6-1962-g59773924
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
TypeKeyed.h
Go to the documentation of this file.
1 
11 // Copyright 2015 Sensics, Inc.
12 // TypePack is part of OSVR-Core.
13 //
14 // Use, modification and distribution is subject to the
15 // Boost Software License, Version 1.0. (See accompanying
16 // file LICENSE_1_0.txt or copy at
17 // http://www.boost.org/LICENSE_1_0.txt)
18 
19 #ifndef INCLUDED_TypeKeyed_h_GUID_49539B71_1F6F_4A84_B681_4FD65F87A2A8
20 #define INCLUDED_TypeKeyed_h_GUID_49539B71_1F6F_4A84_B681_4FD65F87A2A8
21 
22 // Internal Includes
23 #include "Contains.h"
24 #include "FindFirst.h"
25 #include "T.h"
26 
27 // Library/third-party includes
28 // - none
29 
30 // Standard includes
31 #include <tuple>
32 #include <type_traits>
33 
34 namespace osvr {
35 namespace typepack {
36  // Forward declaration
37  template <typename Derived> class TypeKeyedBase;
38 
39  namespace typekeyed_detail {
43  template <typename Derived, typename Key>
45 
50  template <typename Derived> struct KeyTypesTraits {
51  using type = typename Derived::key_types;
52  };
53 
56  template <typename Derived>
57  using key_types = t_<KeyTypesTraits<Derived>>;
58 
61  template <typename Derived, typename Key>
62  using valid_key = contains<key_types<Derived>, Key>;
63 
66  template <typename Derived, typename Key>
67  using index = find_first<key_types<Derived>, Key>;
68 
71  template <typename Derived, typename Key>
72  using value_type_at_key = t_<ValueTypeAtKeyTraits<Derived, Key>>;
73 
76  template <typename Derived, typename Key>
77  using ref_type_at_key =
78  std::add_lvalue_reference<value_type_at_key<Derived, Key>>;
79 
82  template <typename Derived, typename Key>
83  using rref_type_at_key =
84  std::add_rvalue_reference<value_type_at_key<Derived, Key>>;
85 
88  template <typename Derived, typename Key>
89  using cref_type_at_key = std::add_lvalue_reference<
91 
102  template <typename Derived, typename Key> struct ValueAccessor {
103  static_assert(valid_key<Derived, Key>::value,
104  "Key type not found in the list!");
105  using reference = typename ref_type_at_key<Derived, Key>::type;
106  using rvalue_reference =
107  typename rref_type_at_key<Derived, Key>::type;
108  using const_reference =
109  typename cref_type_at_key<Derived, Key>::type;
110  using Index = index<Derived, Key>;
111  static reference get_reference(TypeKeyedBase<Derived> &c);
112  static const_reference
113  get_const_reference(TypeKeyedBase<Derived> const &c);
114  static rvalue_reference
115  get_rvalue_reference(TypeKeyedBase<Derived> &&c);
116  };
117 
118  // forward declaration
119  template <typename Key, typename Derived>
120  typename ref_type_at_key<Derived, Key>::type
121  get(TypeKeyedBase<Derived> &c);
122 
123  // forward declaration
124  template <typename Key, typename Derived>
125  typename rref_type_at_key<Derived, Key>::type
127 
128  // forward declaration
129  template <typename Key, typename Derived>
130  typename cref_type_at_key<Derived, Key>::type
131  cget(TypeKeyedBase<Derived> const &c);
132  } // namespace typekeyed_detail
133 
138  template <typename Derived> class TypeKeyedBase {
139  public:
140  using DerivedType = Derived;
141 
144  template <typename Key>
145  typename typekeyed_detail::ref_type_at_key<Derived, Key>::type
146  get(Key const * = nullptr) {
147  return typekeyed_detail::get<Key>(*this);
148  }
149 
152  template <typename Key>
153  typename typekeyed_detail::cref_type_at_key<Derived, Key>::type
154  get(Key const * = nullptr) const {
155  return typekeyed_detail::cget<Key>(*this);
156  }
157 
158  private:
160  DerivedType &derived() { return *static_cast<DerivedType *>(this); }
161 
163  DerivedType const &derived() const {
164  return *static_cast<DerivedType const *>(this);
165  }
166 
168  DerivedType const &const_derived() const {
169  return *static_cast<DerivedType const *>(this);
170  }
171 
172  // befriend the only consumer of our `derived()` methods.
173  template <typename, typename>
174  friend struct typekeyed_detail::ValueAccessor;
175  };
176 
177  namespace typekeyed_detail {
178  template <typename Derived, typename Key>
179  inline typename ref_type_at_key<Derived, Key>::type
180  ValueAccessor<Derived, Key>::get_reference(TypeKeyedBase<Derived> &c) {
181  return std::get<Index::value>(c.derived().nested_container());
182  }
183  template <typename Derived, typename Key>
184  inline typename cref_type_at_key<Derived, Key>::type
185  ValueAccessor<Derived, Key>::get_const_reference(
186  TypeKeyedBase<Derived> const &c) {
187  return std::get<Index::value>(c.derived().nested_container());
188  }
189  template <typename Derived, typename Key>
190  inline typename rref_type_at_key<Derived, Key>::type
191  ValueAccessor<Derived, Key>::get_rvalue_reference(
192  TypeKeyedBase<Derived> &&c) {
193  return std::forward<rvalue_reference>(
194  std::get<Index::value>(c.derived().nested_container()));
195  }
198  template <typename Key, typename Derived>
199  inline typename ref_type_at_key<Derived, Key>::type
201  static_assert(valid_key<Derived, Key>::value,
202  "Key type not found in the list!");
204  }
207  template <typename Key, typename Derived>
208  inline typename rref_type_at_key<Derived, Key>::type
210  static_assert(valid_key<Derived, Key>::value,
211  "Key type not found in the list!");
212  return std::forward<rref_type_at_key<Derived, Key>>(
214  std::forward<TypeKeyedBase<Derived> &&>(c)));
215  }
216 
219  template <typename Key, typename Derived>
220  inline typename cref_type_at_key<Derived, Key>::type
222  static_assert(valid_key<Derived, Key>::value,
223  "Key type not found in the list!");
225  }
226 
227  } // namespace typekeyed_detail
228 
233  template <typename Key, typename Derived>
234  inline typename typekeyed_detail::ref_type_at_key<Derived, Key>::type
236  return typekeyed_detail::get<Key>(c);
237  }
238 
243  template <typename Key, typename Derived>
244  inline typename typekeyed_detail::rref_type_at_key<Derived, Key>::type
246  return std::forward<typekeyed_detail::rref_type_at_key<Derived, Key>>(
247  typekeyed_detail::rget<Key>(c));
248  }
256  template <typename Key, typename Derived>
257  inline typename typekeyed_detail::cref_type_at_key<Derived, Key>::type
259  return typekeyed_detail::cget<Key>(c);
260  }
261 } // namespace typepack
262 } // namespace osvr
263 #endif // INCLUDED_TypeKeyed_h_GUID_49539B71_1F6F_4A84_B681_4FD65F87A2A8
apply_list< quote< or_ >, transform< Haystack, detail::is_< Needle >>> contains
Determines if type Needle is in the list Haystack - is an alias for a type that inherits std::true_ty...
Definition: Contains.h:49
The main namespace for all C++ elements of the framework, internal and external.
Definition: ClientKit.h:31
Header.
rref_type_at_key< Derived, Key >::type rget(TypeKeyedBase< Derived > &&c)
Definition: TypeKeyed.h:209
Header.
cref_type_at_key< Derived, Key >::type cget(TypeKeyedBase< Derived > const &c)
Definition: TypeKeyed.h:221
typekeyed_detail::rref_type_at_key< Derived, Key >::type rget(TypeKeyedBase< Derived > &&c)
Definition: TypeKeyed.h:245
t_< detail::find_first_impl< Needle, 0, List >> find_first
Returns the zero-based index of the first instance of Needle in List. Will fail to compile if not fou...
Definition: FindFirst.h:61
typename T::type t_
A convenience alias template to extract the nested type within the supplied T.
Definition: T.h:52
typekeyed_detail::cref_type_at_key< Derived, Key >::type cget(TypeKeyedBase< Derived > const &c)
Definition: TypeKeyed.h:258
Header.