nlib
TypeTraits.h
Go to the documentation of this file.
1 
2 #pragma once
3 #ifndef INCLUDE_NN_NLIB_TYPETRAITS_H_
4 #define INCLUDE_NN_NLIB_TYPETRAITS_H_
5 
6 #include "nn/nlib/Config.h"
7 
8 #ifndef NLIB_HAS_NATIVE_TYPETRAITS
9 
10 #ifdef __GLIBCXX__
11 #include <type_traits> // NOLINT
12 #endif
13 
14 NLIB_NAMESPACE_BEGIN
15 
16 // for std::integral_constant
17 template<class T, T v>
18 struct IntegralConstant {
19  static const T value = v;
20  typedef T value_type;
21  typedef IntegralConstant type;
22  operator value_type() const { return value; }
23 };
24 
25 // for std::true_type, std::false_type
26 typedef IntegralConstant<bool, true> TrueType;
27 typedef IntegralConstant<bool, false> FalseType;
28 
29 #define NLIB_DEF_TRUETYPE(name, tp) \
30  template<> struct name<tp> { typedef TrueType type; }
31 
32 namespace tt_detail {
33 
34 template<class T> struct my_or1 { typedef T type; };
35 
36 template<class T1, class T2> struct my_or2;
37 template<class T> struct my_or2<TrueType, T> { typedef TrueType type; };
38 template<class T> struct my_or2<FalseType, T> {
39  typedef typename my_or1<T>::type type;
40 };
41 
42 template<class T1, class T2, class T3> struct my_or3;
43 template<class T1, class T2> struct my_or3<TrueType, T1, T2> {
44  typedef TrueType type;
45 };
46 template<class T1, class T2> struct my_or3<FalseType, T1, T2> {
47  typedef typename my_or2<T1, T2>::type type;
48 };
49 
50 template<class T1, class T2, class T3, class T4> struct my_or4;
51 template<class T1, class T2, class T3> struct my_or4<TrueType, T1, T2, T3> {
52  typedef TrueType type;
53 };
54 template<class T1, class T2, class T3> struct my_or4<FalseType, T1, T2, T3> {
55  typedef typename my_or3<T1, T2, T3>::type type;
56 };
57 
58 template<class T1 = FalseType, class T2 = FalseType,
59  class T3 = FalseType, class T4 = FalseType>
60 struct my_or {
61  typedef typename my_or4<T1, T2, T3, T4>::type type;
62 };
63 
64 } // namespace tt_detail
65 
66 // for std::enable_if
67 template<bool B, class T = void> struct EnableIf {};
68 template<class T> struct EnableIf<true, T> { typedef T type; };
69 
70 // for std::conditional
71 template<bool B, class T, class F> struct Conditional { typedef T type; };
72 template<class T, class F> struct Conditional<false, T, F> { typedef F type; };
73 
74 // for std::remove_cv
75 template<class T> struct RemoveConst { typedef T type; };
76 template<class T> struct RemoveConst<const T> { typedef T type; };
77 
78 template<class T> struct RemoveVolatile { typedef T type; };
79 template<class T> struct RemoveVolatile<volatile T> { typedef T type; };
80 
81 template<class T>
82 struct RemoveCv {
83  typedef typename RemoveVolatile<typename RemoveConst<T>::type>::type type;
84 };
85 
86 // for std::remove_pointer
87 template<class T> struct RemovePtr { typedef T type; };
88 template<class T> struct RemovePtr<T*> { typedef T type; };
89 template<class T> struct RemovePtr<const T*> { typedef T type; };
90 template<class T> struct RemovePtr<volatile T*> { typedef T type; };
91 template<class T> struct RemovePtr<const volatile T*> { typedef T type; };
92 
93 // for std::remove_reference
94 template<class T> struct RemoveRef { typedef T type; };
95 template<class T> struct RemoveRef<T&> { typedef T type; };
96 
97 template<class T> struct AddRef { typedef T& type; };
98 template<> struct AddRef<void> { typedef void type; };
99 
100 // for std::is_same
101 template<class T1, class T2> struct IsSame : public FalseType {};
102 template<class T> struct IsSame<T, T> : public TrueType {};
103 
104 // for std::is_void
105 namespace tt_detail {
106 template<class T> struct is_void { typedef FalseType type; };
107 NLIB_DEF_TRUETYPE(is_void, void);
108 }
109 
110 template<class T>
111 struct IsVoid :
112  public tt_detail::is_void<typename RemoveCv<T>::type>::type {
113 };
114 
115 // for std::is_integral
116 namespace tt_detail {
117 
118 template<class T> struct is_integral_ex { typedef FalseType type; };
119 NLIB_DEF_TRUETYPE(is_integral_ex, signed char);
120 NLIB_DEF_TRUETYPE(is_integral_ex, signed short); // NOLINT
121 NLIB_DEF_TRUETYPE(is_integral_ex, signed int);
122 NLIB_DEF_TRUETYPE(is_integral_ex, signed long); // NOLINT
123 NLIB_DEF_TRUETYPE(is_integral_ex, signed long long); // NOLINT
124 
125 template<class T> struct is_integral { typedef FalseType type; };
126 NLIB_DEF_TRUETYPE(is_integral, bool);
127 NLIB_DEF_TRUETYPE(is_integral, char);
128 NLIB_DEF_TRUETYPE(is_integral, wchar_t);
129 NLIB_DEF_TRUETYPE(is_integral, short); // NOLINT
130 NLIB_DEF_TRUETYPE(is_integral, int);
131 NLIB_DEF_TRUETYPE(is_integral, long); // NOLINT
132 NLIB_DEF_TRUETYPE(is_integral, long long); // NOLINT
133 
134 NLIB_DEF_TRUETYPE(is_integral, unsigned char);
135 NLIB_DEF_TRUETYPE(is_integral, unsigned short); // NOLINT
136 NLIB_DEF_TRUETYPE(is_integral, unsigned int);
137 NLIB_DEF_TRUETYPE(is_integral, unsigned long long); // NOLINT
138 NLIB_DEF_TRUETYPE(is_integral, unsigned long); // NOLINT
139 } // namespace tt_detail
140 
141 template<class T>
142 struct IsIntegral
143  : public tt_detail::my_or<
144  typename tt_detail::is_integral<typename RemoveCv<T>::type>::type,
145  typename tt_detail::is_integral_ex<typename RemoveCv<T>::type>::type
146  >::type {
147 };
148 
149 // for std::is_signed
150 namespace tt_detail {
151 
152 template<class T> struct is_signed_ex { typedef FalseType type; };
153 NLIB_DEF_TRUETYPE(is_signed_ex, signed char);
154 NLIB_DEF_TRUETYPE(is_signed_ex, signed short); // NOLINT
155 NLIB_DEF_TRUETYPE(is_signed_ex, signed int);
156 NLIB_DEF_TRUETYPE(is_signed_ex, signed long); // NOLINT
157 NLIB_DEF_TRUETYPE(is_signed_ex, signed long long); // NOLINT
158 
159 template<class T> struct is_signed { typedef FalseType type; };
160 NLIB_DEF_TRUETYPE(is_signed, char);
161 NLIB_DEF_TRUETYPE(is_signed, short); // NOLINT
162 NLIB_DEF_TRUETYPE(is_signed, int);
163 NLIB_DEF_TRUETYPE(is_signed, long); // NOLINT
164 NLIB_DEF_TRUETYPE(is_signed, long long); // NOLINT
165 NLIB_DEF_TRUETYPE(is_signed, float);
166 NLIB_DEF_TRUETYPE(is_signed, double);
167 } // namespace tt_detail
168 
169 template<class T>
170 struct IsSigned
171  : public tt_detail::my_or<
172  typename tt_detail::is_signed<typename RemoveCv<T>::type>::type,
173  typename tt_detail::is_signed_ex<typename RemoveCv<T>::type>::type
174  >::type {
175 };
176 
177 template<class T> struct IsUnsigned { typedef FalseType type; };
178 template<> struct IsUnsigned<bool> { typedef TrueType type; };
179 template<> struct IsUnsigned<wchar_t> { typedef TrueType type; };
180 template<> struct IsUnsigned<unsigned char> { typedef TrueType type; };
181 template<> struct IsUnsigned<unsigned short> { typedef TrueType type; }; // NOLINT
182 template<> struct IsUnsigned<unsigned int> { typedef TrueType type; };
183 template<> struct IsUnsigned<unsigned long> { typedef TrueType type; }; // NOLINT
184 template<> struct IsUnsigned<unsigned long long> { typedef TrueType type; }; // NOLINT
185 
186 // for std::is_floating_point
187 namespace tt_detail {
188 
189 template<class T> struct is_floating_point { typedef FalseType type; };
190 NLIB_DEF_TRUETYPE(is_floating_point, float);
191 NLIB_DEF_TRUETYPE(is_floating_point, double);
192 NLIB_DEF_TRUETYPE(is_floating_point, long double);
193 
194 }
195 
196 template<class T>
197 struct IsFloatingPoint
198  : public tt_detail::is_floating_point<typename RemoveCv<T>::type>::type {
199 };
200 
201 // for std::is_arithmetic
202 template<class T>
203 struct IsArithmetic
204  : public IntegralConstant<
205  bool,
206  IsIntegral<T>::value || IsFloatingPoint<T>::value> {
207 };
208 
209 // for std::is_pointer
210 namespace tt_detail {
211 template<class T> struct IsPointerHelper : public FalseType {};
212 template<class T> struct IsPointerHelper<T*> : public TrueType {};
213 }
214 template<class T>
215 struct IsPointer :
216  public tt_detail::IsPointerHelper<typename RemoveCv<T>::type> {
217 };
218 
219 // for std::is_reference
220 template<class T> struct IsReference : public FalseType {};
221 template<class T> struct IsReference<T&> : public TrueType {};
222 
223 // for std::is_array
224 template<class T> struct IsArray : public FalseType {};
225 template<class T> struct IsArray<T[]> : public TrueType {};
226 template<class T, size_t N>
227 struct IsArray<T[N]> : public TrueType {};
228 
229 // for std::is_member_pointer
230 namespace tt_detail {
231 template<class T> struct is_member_pointer : public FalseType {};
232 template<class T, class U>
233 struct is_member_pointer<T U::*> : public TrueType {};
234 }
235 template<class T>
236 struct IsMemberPointer :
237  public tt_detail::is_member_pointer<typename RemoveCv<T>::type> {
238 };
239 
240 // for std::is_function
241 namespace tt_detail {
242 template<bool B> struct is_function_ { typedef FalseType type; };
243 template<> struct is_function_<true> { typedef TrueType type; };
244 template<class T>
245 struct is_function {
246  private:
247  typedef char One;
248  typedef struct { char a[2]; } Two;
249  template<class U> static One test(...);
250  template<class U> static Two test(U (*)[1]);
251 
252  public:
253 #ifdef CAFE
254 # pragma diag_suppress 1931
255 #endif
256  typedef typename is_function_<sizeof(test<T>(0)) == 1>::type type;
257 #ifdef CAFE
258 # pragma diag_warning 1931
259 #endif
260 };
261 template<class T> struct is_function<T&> { typedef FalseType type; };
262 template<> struct is_function<void> { typedef FalseType type; };
263 template<> struct is_function<const void> { typedef FalseType type; };
264 template<> struct is_function<volatile void> { typedef FalseType type; };
265 template<> struct is_function<const volatile void> { typedef FalseType type; };
266 } // namespace tt_detail
267 template<class T>
268 struct IsFunction : public tt_detail::is_function<T>::type {};
269 
270 #if !defined(NN_PLATFORM_CTR)
271 template<class T>
272 struct IsEnum :
273  public IntegralConstant<bool, __is_enum(T)> {
274 };
275 #else
276 // for std::is_enum
277 namespace tt_detail {
278 typedef char (&SizeOverOne)[2];
279 template<class T,
280  bool convert_possible =
281  !IsArithmetic<T>::value &&
282  !IsReference<T>::value &&
283  !IsPointer<T>::value &&
284  !IsMemberPointer<T>::value &&
285  !IsFunction<T>::value &&
286  !IsVoid<T>::value &&
287  !IsArray<T>::value>
288 struct ConsumeUDC {
289  operator T() const;
290 };
291 template<class T>
292 struct ConsumeUDC<T, false> {
293  operator SizeOverOne() const;
294 };
295 char enum_check(bool x);
296 char enum_check(char x);
297 char enum_check(signed char x);
298 char enum_check(unsigned char x);
299 char enum_check(wchar_t x);
300 char enum_check(signed short x); // NOLINT
301 char enum_check(unsigned short x); // NOLINT
302 char enum_check(signed int x);
303 char enum_check(unsigned int x);
304 char enum_check(signed long x); // NOLINT
305 char enum_check(unsigned long x); // NOLINT
306 char enum_check(signed long long x); // NOLINT
307 char enum_check(unsigned long long x); // NOLINT
308 char enum_check(float x);
309 char enum_check(double x);
310 char enum_check(long double x);
311 SizeOverOne enum_check(SizeOverOne x);
312 SizeOverOne enum_check(...);
313 template<class T>
314 struct is_enum {
315  enum {
316  value = sizeof(enum_check(ConsumeUDC<T>())) == 1
317  };
318 };
319 } // namespace tt_detail
320 
321 template<class T>
322 struct IsEnum
323  : public IntegralConstant<bool, tt_detail::is_enum<T>::value> {};
324 #endif
325 
326 #if !defined(NN_PLATFORM_CTR) && !defined(CAFE)
327 template<class T>
328 struct IsPod :
329  public IntegralConstant<bool,
330  __is_pod(T) || IsEnum<T>::value ||
331  IsArithmetic<T>::value || IsPointer<T>::value ||
332  IsMemberPointer<T>::value> {
333 };
334 
335 template<class T>
336 struct IsTriviallyDestructible :
337  public IntegralConstant<bool, __has_trivial_destructor(T)> {
338 };
339 #ifdef _MSC_VER
340 template<class T>
341 struct IsTriviallyDefaultConstructible :
342  public IntegralConstant<bool, __has_trivial_default_constructor(T)> {
343 };
344 #else
345 template<class T>
346 struct IsTriviallyDefaultConstructible :
347  public IntegralConstant<bool, std::has_trivial_default_constructor<T>::value > {
348 };
349 #endif
350 
351 #else
352 // for std::is_pod
353 namespace tt_detail {
354 
355 template<class T> struct is_pod
356  : public tt_detail::my_or<typename IsArithmetic<T>::type,
357  typename IsPointer<T>::type,
358  typename IsMemberPointer<T>::type,
359  typename IsEnum<T>::type>::type {
360 };
361 
362 template<class T>
363 struct is_pod<T[]> {
364  typedef typename is_pod<typename RemoveCv<T>::type>::type type;
365 };
366 template<class T, size_t N>
367 struct is_pod<T[N]> {
368  typedef typename is_pod<typename RemoveCv<T>::type>::type type;
369 };
370 
371 } // namespace tt_detail
372 
373 // NOTE: internal use only
374 // treats enum as non-POD.
375 // treats struct as non-POD.
376 //
377 // You have to define specialized IsPod when you have to use IsPos on struct.
378 // example:
379 // template<> struct IsPod<MyType> : public TrueType {};
380 template<class T>
381 struct IsTriviallyDestructible
382  : public tt_detail::is_pod<typename RemoveCv<T>::type>::type {
383 };
384 template<class T>
385 struct IsTriviallyDefaultConstructible
386  : public tt_detail::is_pod<typename RemoveCv<T>::type>::type {
387 };
388 
389 template<class T>
390 struct IsPod : public IsTriviallyDestructible<T> {};
391 #endif
392 
393 #if !defined(NN_PLATFORM_CTR)
394 template<class T>
395 struct IsEmpty :
396  public IntegralConstant<bool, __is_empty(T)> {
397 };
398 #else
399 // for std::is_empty
400 namespace tt_detail {
401 template<class T>
402 struct IsEmptyHelper1 : public T {
403  int data[256];
404 
405  private:
406  NLIB_DISALLOW_COPY_AND_ASSIGN(IsEmptyHelper1);
407 };
408 
409 struct IsEmptyHelper2 { int data[256]; };
410 } // namespace tt_detail
411 
412 template<class T>
413 struct IsEmpty :
414  public IntegralConstant<bool, sizeof(tt_detail::IsEmptyHelper1<T>) ==
415  sizeof(tt_detail::IsEmptyHelper2)> {
416 };
417 #endif
418 
419 #if !defined(NN_PLATFORM_CTR)
420 template<class T>
421 struct IsClass :
422  public IntegralConstant<bool, __is_class(T)> {
423 };
424 #else
425 // note that IsClass<union type>::value becomes true
426 template<class T>
427 class IsClass {
428  typedef char yes;
429  typedef struct { char a[2]; } no;
430 
431  template<class X>
432  static yes check(void (X::*)(void));
433  template<class X>
434  static no check(...);
435 
436  public:
437  static const bool value = sizeof(check<T>(NULL)) == sizeof(yes);
438 };
439 #endif
440 
441 // template<class T> struct AddLvalueReference { typedef T& type; };
442 // template<class T> struct AddLvalueReference<T&> { typedef T& type; };
443 
444 NLIB_NAMESPACE_END
445 
446 #undef NLIB_DEF_TRUETYPE
447 #else
448 
449 #include <type_traits> // NOLINT
450 NLIB_NAMESPACE_BEGIN
451 
452 #ifdef NLIB_HAS_TR1_TYPETRAITS
453 #define NLIB_DEF_REDIRECT(nlibstruct, stdstruct) \
454 template<class T> struct nlibstruct \
455  : public std::tr1::stdstruct<T> {}
456 template<class T, T v>
457 struct IntegralConstant
458  : public std::tr1::integral_constant<T, v> {
459 };
460 typedef std::tr1::true_type TrueType;
461 typedef std::tr1::false_type FalseType;
462 template<bool B, class T = void> struct EnableIf {};
463 template<class T> struct EnableIf<true, T> { typedef T type; };
464 template<bool B, class T, class F> struct Conditional { typedef T type; };
465 template<class T, class F> struct Conditional<false, T, F> { typedef F type; };
466 template<class T1, class T2>
467 struct IsSame : public std::tr1::is_same<T1, T2> {};
468 
469 NLIB_DEF_REDIRECT(IsTriviallyDestructible, has_trivial_destructor);
470 NLIB_DEF_REDIRECT(IsTriviallyDefaultConstructible, has_trivial_default_constructor);
471 
472 #else
473 #define NLIB_DEF_REDIRECT(nlibstruct, stdstruct) \
474 template<class T> struct nlibstruct \
475  : public std::stdstruct<T> {}
476 template<class T, T v>
477 struct IntegralConstant
478  : public std::integral_constant<T, v> {
479 };
480 typedef std::true_type TrueType;
481 typedef std::false_type FalseType;
482 template<bool B, class T> struct EnableIf : public std::enable_if<B, T> {};
483 template<bool B, class T, class F>
484 struct Conditional
485  : public std::conditional<B, T, F> {
486 };
487 template<class T1, class T2>
488 struct IsSame : public std::is_same<T1, T2> {};
489 
490 // still unimplemented
491 // #if defined(__GLIBCXX__) && __GLIBCXX__ <= 20141011
492 #if defined(__GLIBCXX__)
493 template<class T>
494 struct IsTriviallyDestructible :
495  public IntegralConstant<bool, __has_trivial_destructor(T)> {
496 };
497 template<class T>
498 struct IsTriviallyDefaultConstructible :
499  public IntegralConstant<bool, __has_trivial_constructor(T)> {
500 };
501 #else
502 NLIB_DEF_REDIRECT(IsTriviallyDestructible, is_trivially_destructible);
503 NLIB_DEF_REDIRECT(IsTriviallyDefaultConstructible, is_trivially_constructible);
504 #endif
505 
506 #endif
507 
508 NLIB_DEF_REDIRECT(RemoveConst, remove_const);
509 NLIB_DEF_REDIRECT(RemoveVolatile, remove_volatile);
510 NLIB_DEF_REDIRECT(RemovePtr, remove_pointer);
511 NLIB_DEF_REDIRECT(RemoveRef, remove_reference);
512 NLIB_DEF_REDIRECT(AddRef, add_lvalue_reference);
513 NLIB_DEF_REDIRECT(RemoveCv, remove_cv);
514 NLIB_DEF_REDIRECT(IsVoid, is_void);
515 NLIB_DEF_REDIRECT(IsIntegral, is_integral);
516 NLIB_DEF_REDIRECT(IsSigned, is_signed);
517 NLIB_DEF_REDIRECT(IsUnsigned, is_unsigned);
518 NLIB_DEF_REDIRECT(IsFloatingPoint, is_floating_point);
519 NLIB_DEF_REDIRECT(IsArithmetic, is_arithmetic);
520 NLIB_DEF_REDIRECT(IsPointer, is_pointer);
521 NLIB_DEF_REDIRECT(IsReference, is_reference);
522 NLIB_DEF_REDIRECT(IsArray, is_array);
523 NLIB_DEF_REDIRECT(IsMemberPointer, is_member_pointer);
524 NLIB_DEF_REDIRECT(IsFunction, is_function);
525 NLIB_DEF_REDIRECT(IsEnum, is_enum);
526 
527 NLIB_DEF_REDIRECT(IsPod, is_pod);
528 NLIB_DEF_REDIRECT(IsEmpty, is_empty);
529 NLIB_DEF_REDIRECT(IsClass, is_class);
530 
531 NLIB_NAMESPACE_END
532 
533 #undef NLIB_DEF_REDIRECT
534 #endif
535 
536 NLIB_NAMESPACE_BEGIN
537 
538 namespace detail {
539 
540 template<class T>
541 class HasSwapMemFn {
542  typedef char yes;
543  typedef struct { char a[2]; } no;
544 
545  template<class X, void (X::*Func)(T&)>
546  struct helper {};
547  template<class X>
548  static yes check(helper<X, &X::swap>* p);
549  template<class X>
550  static no check(...);
551 
552  public:
553 #ifdef CAFE
554 # pragma diag_suppress 1931
555 #endif
556  static const bool value = sizeof(check<T>(NULL)) == sizeof(yes);
557 #ifdef CAFE
558 # pragma diag_warning 1931
559 #endif
560 };
561 
562 template<class T, bool isClass>
563 struct IsSwappable_ :
564  public IntegralConstant<bool, detail::HasSwapMemFn<T>::value> {
565 };
566 
567 template<class T>
568 struct IsSwappable_<T, false> :
569  public IntegralConstant<
570  bool,
571  IsArithmetic<T>::value ||
572  IsPointer<T>::value ||
573  IsFunction<T>::value ||
574  IsMemberPointer<T>::value ||
575  IsEnum<T>::value
576  > {
577 };
578 
579 } // namespace detail
580 
581 // true if T has swap(T&) member function
582 // or T is a simple value.
583 // T may be swappable if IsSwappable<T>::value is false.
584 template<class T>
585 struct IsSwappable : public detail::IsSwappable_<T, IsClass<T>::value> {};
586 
587 NLIB_NAMESPACE_END
588 
589 #endif // INCLUDE_NN_NLIB_TYPETRAITS_H_
#define NLIB_DISALLOW_COPY_AND_ASSIGN(TypeName)
Prohibits use of the copy constructor and assignment operator for the class specified by TypeName...
Definition: Config.h:145
A file that contains the configuration information for each development environment.