SMTK  @SMTK_VERSION@
Simulation Modeling Tool Kit
TypeName.h
Go to the documentation of this file.
1 //=========================================================================
2 // Copyright (c) Kitware, Inc.
3 // All rights reserved.
4 // See LICENSE.txt for details.
5 //
6 // This software is distributed WITHOUT ANY WARRANTY; without even
7 // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
8 // PURPOSE. See the above copyright notice for more information.
9 //=========================================================================
10 
11 #ifndef smtk_common_TypeName_h
12 #define smtk_common_TypeName_h
13 
14 #include "smtk/TupleTraits.h"
15 
16 #include "smtk/common/CompilerInformation.h"
17 
18 #include <boost/type_index.hpp>
19 
20 #include <array>
21 #include <deque>
22 #include <forward_list>
23 #include <list>
24 #include <map>
25 #include <memory>
26 #include <queue>
27 #include <set>
28 #include <stack>
29 #include <string>
30 #include <tuple>
31 #include <typeinfo>
32 #include <unordered_map>
33 #include <unordered_set>
34 #include <vector>
35 
36 namespace smtk
37 {
38 namespace common
39 {
51 
52 namespace detail
53 {
55 template<typename T>
56 class is_named
57 {
58  template<typename X>
59  static std::true_type testNamed(decltype(X::type_name)*);
60  template<typename X>
61  static std::false_type testNamed(...);
62 
63 public:
64  using type = decltype(testNamed<T>(nullptr));
65 };
66 
67 template<typename Type>
68 struct name
69 {
70  // If there's a user-defined type_name field, use it.
71  template<typename T>
72  static typename std::enable_if<is_named<T>::type::value, std::string>::type value_()
73  {
74  return T::type_name;
75  }
76 
78  template<typename T>
79  static typename std::enable_if<!is_named<T>::type::value, std::string>::type value_()
80  {
81 #ifdef SMTK_MSVC
82  // MSVC's implementation of type_name refers to classes as "class foo". To
83  // maintain parity with other compilers, we strip the preceding "class "
84  // away. We do the same for "struct ".
85  std::string pretty_name = boost::typeindex::type_id<Type>().pretty_name();
86  if (pretty_name.substr(0, 6) == "class ")
87  {
88  pretty_name = pretty_name.substr(6);
89  }
90  else if (pretty_name.substr(0, 7) == "struct ")
91  {
92  pretty_name = pretty_name.substr(7);
93  }
94  // MSVC also uses "`anonymous namespace'" instead of "(anonymous namespace)".
95  // Make that match as well.
96  if (pretty_name.substr(0, 21) == "`anonymous namespace'")
97  {
98  pretty_name = "(anonymous namespace)" + pretty_name.substr(21);
99  }
100  return pretty_name;
101 #else
102  return boost::typeindex::type_id<Type>().pretty_name();
103 #endif
104  }
105 
106  static std::string value() { return value_<Type>(); }
107 };
108 
109 // Specialization for std::string.
110 template<>
111 struct name<std::string>
112 {
113  static std::string value() { return "string"; }
114 };
115 
116 // Specialization for std::tuple.
117 template<typename... Types>
118 struct name<std::tuple<Types...>>
119 {
120  static std::string value()
121  {
122  std::string subtypes = subType<0, std::tuple<Types...>>();
123  return std::string("tuple<" + subtypes + ">");
124  }
125 
126  template<std::size_t I, typename Tuple>
127  inline static typename std::enable_if<I != std::tuple_size<Tuple>::value, std::string>::type
128  subType()
129  {
130  typedef typename std::tuple_element<I, Tuple>::type Type;
131  std::string subtype = name<Type>::value();
132 
133  return (I != 0 ? std::string(", ") : std::string()) + subtype + subType<I + 1, Tuple>();
134  }
135 
136  template<std::size_t I, typename Tuple>
137  inline static typename std::enable_if<I == std::tuple_size<Tuple>::value, std::string>::type
138  subType()
139  {
140  return std::string();
141  }
142 };
143 
144 // Specialization for std::array.
145 template<typename Type, size_t N>
146 struct name<std::array<Type, N>>
147 {
148  static std::string value()
149  {
150  std::string subtype = name<Type>::value();
151  return std::string("array<" + subtype + "," + std::to_string(N) + ">");
152  }
153 };
154 
155 // Specialization for std::priority_queue.
156 template<typename Type>
157 struct name<std::priority_queue<Type, std::vector<Type>, std::less<Type>>>
158 {
159  static std::string value()
160  {
161  std::string subtype = name<Type>::value();
162 
163  return std::string("priority_queue<" + subtype + ">");
164  }
165 };
166 
167 // Specialization for smart pointers.
168 #define name_single_argument_stl_pointer(POINTER) \
169  template<typename Type> \
170  struct name<std::POINTER<Type>> \
171  { \
172  static std::string value() \
173  { \
174  std::string subtype = name<Type>::value(); \
175  return std::string(#POINTER) + "<" + subtype + ">"; \
176  } \
177  }
178 
179 name_single_argument_stl_pointer(shared_ptr);
180 name_single_argument_stl_pointer(weak_ptr);
181 name_single_argument_stl_pointer(unique_ptr);
182 
183 // Specialization for containers with allocators.
184 #undef name_single_argument_stl_container
185 
186 #define name_single_argument_stl_container(CONTAINER) \
187  template<typename Type> \
188  struct name<std::CONTAINER<Type, std::allocator<Type>>> \
189  { \
190  static std::string value() \
191  { \
192  std::string subtype = name<Type>::value(); \
193  return std::string(#CONTAINER) + "<" + subtype + ">"; \
194  } \
195  }
196 
197 name_single_argument_stl_container(vector);
198 name_single_argument_stl_container(deque);
199 name_single_argument_stl_container(forward_list);
200 name_single_argument_stl_container(list);
201 
202 #undef name_single_argument_stl_container
203 
204 // Specialization for containers with allocators and comparators.
205 #define name_single_argument_sorted_stl_container(CONTAINER) \
206  template<typename Type> \
207  struct name<std::CONTAINER<Type, std::less<Type>, std::allocator<Type>>> \
208  { \
209  static std::string value() \
210  { \
211  std::string subtype = name<Type>::value(); \
212  return std::string(#CONTAINER) + "<" + subtype + ">"; \
213  } \
214  }
215 
216 name_single_argument_sorted_stl_container(set);
217 name_single_argument_sorted_stl_container(multiset);
218 name_single_argument_sorted_stl_container(unordered_set);
219 name_single_argument_sorted_stl_container(unordered_multiset);
220 
221 #undef name_single_argument_sorted_stl_container
222 
223 // Specialization for containers that accept a type and container type.
224 #define name_double_argument_stl_container(CONTAINER) \
225  template<typename Type> \
226  struct name<std::CONTAINER<Type, std::deque<Type>>> \
227  { \
228  static std::string value() \
229  { \
230  std::string type = name<Type>::value(); \
231  return std::string(#CONTAINER) + "<" + type + ">"; \
232  } \
233  }
234 
235 name_double_argument_stl_container(queue);
236 name_double_argument_stl_container(stack);
237 
238 #undef name_double_argument_stl_container
239 
240 // Specialization for containers that accept a key, value, comparator and allocator.
241 #define name_double_argument_sorted_stl_container(CONTAINER) \
242  template<typename KeyType, typename ValueType> \
243  struct name<std::CONTAINER< \
244  KeyType, \
245  ValueType, \
246  std::less<KeyType>, \
247  std::allocator<std::pair<const KeyType, ValueType>>>> \
248  { \
249  static std::string value() \
250  { \
251  std::string keytype = name<KeyType>::value(); \
252  std::string valuetype = name<ValueType>::value(); \
253  return std::string(#CONTAINER) + "<" + keytype + ", " + valuetype + ">"; \
254  } \
255  }
256 
257 name_double_argument_sorted_stl_container(map);
258 name_double_argument_sorted_stl_container(multimap);
259 
260 // Specialization for containers that accept a key, value, comparator and allocator.
261 #define name_double_argument_hashed_stl_container(CONTAINER) \
262  template<typename KeyType, typename ValueType> \
263  struct name<std::CONTAINER< \
264  KeyType, \
265  ValueType, \
266  std::hash<KeyType>, \
267  std::equal_to<KeyType>, \
268  std::allocator<std::pair<const KeyType, ValueType>>>> \
269  { \
270  static std::string value() \
271  { \
272  std::string keytype = name<KeyType>::value(); \
273  std::string valuetype = name<ValueType>::value(); \
274  return std::string(#CONTAINER) + "<" + keytype + ", " + valuetype + ">"; \
275  } \
276  }
277 
278 name_double_argument_hashed_stl_container(unordered_map);
279 name_double_argument_hashed_stl_container(unordered_multimap);
280 
281 #undef name_double_argument_hashed_stl_container
282 } // namespace detail
283 
285 template<typename Type>
286 std::string typeName()
287 {
288  return detail::name<Type>::value();
289 }
290 } // namespace common
291 } // namespace smtk
292 
293 #endif // smtk_common_TypeName_h
smtk
The main namespace for the Simulation Modeling Tool Kit (SMTK).
Definition: doc.h:33
smtk::common::detail::is_named
A compile-time test to check whether or not a class has a type_name defined.
Definition: TypeName.h:56
smtk::common::detail::name::value_
static std::enable_if<!is_named< T >::type::value, std::string >::type value_()
By default, we return the prettified type name for the type.
Definition: TypeName.h:79
smtk::common::typeName
std::string typeName()
Return the name of a class.
Definition: TypeName.h:286
smtk::common::detail::name
Definition: TypeName.h:68
TupleTraits.h