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