traits.h
Go to the documentation of this file.
1 #ifndef canvas_Persistency_Common_traits_h
2 #define canvas_Persistency_Common_traits_h
3 
4 /*----------------------------------------------------------------------
5  Definition of traits templates used in the event data model.
6  ----------------------------------------------------------------------*/
7 
10 #include "cetlib/map_vector.h"
11 #include "cetlib/metaprogramming.h"
12 #include "cetlib_except/demangle.h"
13 
14 #include <deque>
15 #include <limits>
16 #include <list>
17 #include <set>
18 #include <string>
19 #include <type_traits>
20 #include <typeinfo>
21 #include <utility>
22 #include <vector>
23 
24 namespace art {
25 
26  // The trait struct template key_traits<K> is used to carry
27  // information relevant to the type K when used as a 'key' in
28  // PtrVector and its related classes and templates.
29  //
30  // The general case works only for integral types K; for more
31  // 'esoteric' types, one must introduce an explicit specialization.
32  // That specialization must initialize the static data member
33  // 'value'.
34 
35  template <typename K>
36  struct key_traits {
37  using key_type = K;
38  static constexpr key_type value{
39  std::numeric_limits<typename key_traits<K>::key_type>::max()};
40  };
41 
42  // Partial specialization for std::pair
43  template <typename U, typename V>
44  struct key_traits<std::pair<U, V>> {
45  using key_type = std::pair<U, V>;
46  static const key_type value;
47  };
48 
49  // If we ever need to support instantiations of std::basic_string
50  // other than std::string, this is the place to do it.
51  // For value, we make a 1-character long string that contains an
52  // unprintable character; we are hoping nobody ever uses such a
53  // string as a legal key.
54  template <>
55  struct key_traits<std::string> {
57  static const key_type value;
58  };
59 
60  template <typename T, typename = void>
61  struct has_value_type : std::false_type {};
62 
63  template <typename T>
64  struct has_value_type<T, std::void_t<typename T::value_type>>
65  : std::true_type {
66  using element_type = typename T::value_type;
67  };
68 
69  template <typename T, typename = void>
70  struct has_mapped_type : std::false_type {};
71 
72  template <typename T>
73  struct has_mapped_type<T, std::void_t<typename T::mapped_type>>
74  : std::true_type {
75  using element_type = typename T::mapped_type;
76  };
77 
78  // A type supports a view if it has a nested 'value_type' or 'mapped_type'
79  // type name.
80  template <typename T, typename = void>
81  struct SupportsView : std::false_type {
82  static std::type_info const*
84  {
85  return nullptr;
86  }
87  };
88 
89  template <typename T>
90  struct SupportsView<
91  T,
92  std::enable_if_t<(has_value_type<T>::value && !has_mapped_type<T>::value)>>
93  : std::true_type {
95  static std::type_info const*
97  {
98  return &typeid(element_type);
99  }
100  };
101 
102  template <typename T>
103  struct SupportsView<T, std::enable_if_t<has_mapped_type<T>::value>>
104  : std::true_type {
106  static std::type_info const*
108  {
109  return &typeid(element_type);
110  }
111  };
112 
113  // The trait struct template has_getView<T> is used to
114  // indicate whether or not the type T has a member function
115  //
116  // std::vector<void const*> T::getView() const
117  //
118  // We assume the 'general case' for T is to not support getView.
119  // Classes which do support getView must specialize this trait.
120 
121  template <typename T>
122  void const*
123  address_of(T const& t) noexcept
124  {
125  return &t;
126  }
127 
128  template <typename T>
129  void const*
131  {
132  return &t.second;
133  }
134 
135  template <typename T, typename = void>
136  struct has_getView {};
137 
138  template <typename T>
139  struct has_getView<
140  T,
141  cet::enable_if_function_exists_t<void (T::*)(std::vector<void const*>&),
142  &T::getView>> {};
143 
144  template <typename T>
145  struct CannotGetView {
146  [[noreturn]] static std::vector<void const*>
147  get(T const&)
148  {
150  << "Product type " << cet::demangle_symbol(typeid(T).name())
151  << " has no getView() capability.\n";
152  }
153  };
154 
155  template <typename T, typename = void>
156  struct MaybeGetView : CannotGetView<T> {};
157 
158  template <typename T>
159  struct MaybeGetView<T, std::enable_if_t<has_getView<T>::value>> {
160  static auto
161  get(T const& product)
162  {
163  return product.getView();
164  }
165  };
166 
167  template <typename T, typename A>
168  struct MaybeGetView<std::vector<T, A>> {
169  static auto
170  get(std::vector<T> const& product)
171  {
172  std::vector<void const*> view;
173  cet::transform_all(product, back_inserter(view), address_of<T>);
174  return view;
175  }
176  };
177 
178  template <typename A>
179  struct MaybeGetView<std::vector<bool, A>>
180  : CannotGetView<std::vector<bool, A>> {};
181 
182  template <typename T, typename A>
183  struct MaybeGetView<std::list<T, A>> {
184  static auto
185  get(std::list<T> const& product)
186  {
187  std::vector<void const*> view;
188  cet::transform_all(product, back_inserter(view), address_of<T>);
189  return view;
190  }
191  };
192 
193  template <typename T, typename A>
194  struct MaybeGetView<std::deque<T, A>> {
195  static auto
196  get(std::deque<T> const& product)
197  {
198  std::vector<void const*> view;
199  cet::transform_all(product, back_inserter(view), address_of<T>);
200  return view;
201  }
202  };
203 
204  template <typename T, typename A>
205  struct MaybeGetView<std::set<T, A>> {
206  static auto
207  get(std::set<T> const& product)
208  {
209  std::vector<void const*> view;
210  cet::transform_all(product, back_inserter(view), address_of<T>);
211  return view;
212  }
213  };
214 
215  template <typename T>
216  struct MaybeGetView<cet::map_vector<T>> {
217  static auto
218  get(cet::map_vector<T> const& product)
219  {
220  std::vector<void const*> view;
221  cet::transform_all(product, back_inserter(view), address_of_second<T>);
222  return view;
223  }
224  };
225 
226  //
227  // The trait struct template has_setPtr<T> is used to
228  // indicate whether or not the type T has a member function
229  //
230  // void T::setPtr(const std::type_info&, void const*&) const
231  //
232  // We assume the 'general case' for T is to not support setPtr.
233  // Classes which do support setPtr must specialize this trait.
234  //
235 
236  template <typename T>
237  struct has_setPtr : std::false_type {};
238  template <typename T, typename A>
239  struct has_setPtr<std::vector<T, A>> : std::true_type {};
240  template <typename A>
241  struct has_setPtr<std::vector<bool, A>> : std::false_type {};
242  template <typename T, typename A>
243  struct has_setPtr<std::list<T, A>> : std::true_type {};
244  template <typename T, typename A>
245  struct has_setPtr<std::deque<T, A>> : std::true_type {};
246  template <typename T, typename A>
247  struct has_setPtr<std::set<T, A>> : std::true_type {};
248  template <typename T>
249  struct has_setPtr<cet::map_vector<T>> : std::true_type {};
250 }
251 
252 #endif /* canvas_Persistency_Common_traits_h */
253 
254 // Local Variables:
255 // mode: c++
256 // End:
static QCString name
Definition: declinfo.cpp:673
std::pair< U, V > key_type
Definition: traits.h:45
static const key_type value
Definition: traits.h:46
std::string string
Definition: nybbler.cc:12
std::pair< key_type, mapped_type > value_type
Definition: map_vector.h:89
STL namespace.
void const * address_of(T const &t) noexcept
Definition: traits.h:123
static std::type_info const * type_id()
Definition: traits.h:96
enable_if_same_t< FT, decltype(f), R > enable_if_function_exists_t
static std::type_info const * type_id()
Definition: traits.h:83
static const key_type value
Definition: traits.h:57
static int max(int a, int b)
auto transform_all(Container &, OutputIt, UnaryOp)
typename has_mapped_type< T >::element_type element_type
Definition: traits.h:105
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
static constexpr key_type value
Definition: traits.h:38
void const * address_of_second(typename cet::map_vector< T >::value_type const &t) noexcept
Definition: traits.h:130
typename has_value_type< T >::element_type element_type
Definition: traits.h:94