Evo C++ Library v0.5.1
meta.h
Go to the documentation of this file.
1 // Evo C++ Library
2 /* Copyright 2019 Justin Crowell
3 Distributed under the BSD 2-Clause License -- see included file LICENSE.txt for details.
4 */
6 
7 #pragma once
8 #ifndef INCL_evo_meta_h
9 #define INCL_evo_meta_h
10 
11 #include "impl/sys.h"
12 
13 namespace evo {
18 
20 
22 template<bool b> struct StaticAssertTrue;
23 template<> struct StaticAssertTrue<true> { };
24 template<int N> struct StaticAssertTestSize { };
34 #define EVO_STATIC_JOIN(A,B) IMPL_EVO_STATIC_JOIN1(A,B)
35 
36 #define IMPL_EVO_STATIC_JOIN1(A,B) IMPL_EVO_STATIC_JOIN2(A,B)
37 #define IMPL_EVO_STATIC_JOIN2(A,B) A##B
38 
40 #if defined(EVO_CPP11)
41 
54  #define STATIC_ASSERT(EXP,TOKEN) static_assert(EXP,#TOKEN)
55 #else
56  #define STATIC_ASSERT(EXP,TOKEN) typedef ::evo::StaticAssertTestSize< sizeof(::evo::StaticAssertTrue<(bool)(EXP)>) > \
57  EVO_STATIC_JOIN(TOKEN, __LINE__) EVO_ATTRIB_UNUSED
58 #endif
59 
60 #if defined(EVO_CPP11)
61 
80  #define STATIC_ASSERT_FUNC_UNUSED =delete;
81 
96  #define STATIC_ASSERT_FUNC_UNUSED_RET(RET) =delete;
97 #elif defined(__clang__)
98  #define STATIC_ASSERT_FUNC_UNUSED ;
99  #define STATIC_ASSERT_FUNC_UNUSED_RET(RET) ;
100 #else
101  #define STATIC_ASSERT_FUNC_UNUSED { ::evo::StaticAssertTrue<false> EVO_STATIC_JOIN(_ASSERT_FUNC_UNUSED_, __LINE__); }
102  #define STATIC_ASSERT_FUNC_UNUSED_RET(RET) { ::evo::StaticAssertTrue<false> EVO_STATIC_JOIN(_ASSERT_FUNC_UNUSED_, __LINE__); return RET; }
103 #endif
104 
106 
111 template<bool val> struct StaticBool {
112  typedef typename evo::StaticBool<val> Type;
113  static const bool value = val;
114 };
115 
118 
121 
134 template<bool b, class T, class F> struct StaticIf { typedef T Type; };
136 template<class T, class F> struct StaticIf<false,T,F> { typedef F Type; };
137 template<class T, class F> struct StaticIf<true,T,F> { typedef T Type; };
140 
152 template<class T1, class T2> struct IsSame : public StaticBoolF { };
154 template<class T> struct IsSame<T,T> : public StaticBoolT { };
168 template<class T> struct IsPointer : public StaticBoolF { };
170 template<class T> struct IsPointer<T*> : public StaticBoolT { };
183 template<class T> struct IsArray : public StaticBoolF { };
185 template<class T> struct IsArray<T[]> : public StaticBoolT { };
186 template<class T, ulong N> struct IsArray<T[N]> : public StaticBoolT { };
199 template<class T> struct IsReference : public StaticBoolF { };
201 template<class T> struct IsReference<T&> : public StaticBoolT { };
215 template<class T> struct IsConst : public StaticBoolF { };
217 template<class T> struct IsConst<const T> : public StaticBoolT { };
229 template<class T> struct IsBool : public StaticBoolF { };
231 template<> struct IsBool<bool> : public StaticBoolT { };
248 template<class T> struct IsInt : public StaticBoolF { };
250 template<> struct IsInt<char> : public StaticBoolT { };
251 template<> struct IsInt<signed char> : public StaticBoolT { };
252 template<> struct IsInt<signed short> : public StaticBoolT { };
253 template<> struct IsInt<signed int> : public StaticBoolT { };
254 template<> struct IsInt<signed long> : public StaticBoolT { };
255 template<> struct IsInt<signed long long> : public StaticBoolT { };
256 template<> struct IsInt<unsigned char> : public StaticBoolT { };
257 template<> struct IsInt<unsigned short> : public StaticBoolT { };
258 template<> struct IsInt<unsigned int> : public StaticBoolT { };
259 template<> struct IsInt<unsigned long> : public StaticBoolT { };
260 template<> struct IsInt<unsigned long long> : public StaticBoolT { };
277 template<class T> struct IsFloat : public StaticBoolF { };
279 template<> struct IsFloat<float> : public StaticBoolT { };
280 template<> struct IsFloat<double> : public StaticBoolT { };
281 template<> struct IsFloat<long double> : public StaticBoolT { };
296 template<class T> struct IsSigned : public StaticBoolT { };
298 template<> struct IsSigned<unsigned char> : public StaticBoolF { };
299 template<> struct IsSigned<unsigned short> : public StaticBoolF { };
300 template<> struct IsSigned<unsigned int> : public StaticBoolF { };
301 template<> struct IsSigned<unsigned long> : public StaticBoolF { };
302 template<> struct IsSigned<unsigned long long> : public StaticBoolF { };
309 template<class T, class U>
311 private:
312  typedef char SmallType;
313  class LargeType { char dummy[2]; };
314  static SmallType check(const U&);
315  static LargeType check(...);
316  static T make();
317 
318 public:
319  static const bool value = (sizeof(check(make())) == sizeof(SmallType));
320 };
321 
323 
325 template<class T> struct AddConst { typedef const T Type; };
327 template<class T> struct AddConst<const T> { typedef T Type; };
331 template<class T> struct RemoveConst { typedef T Type; };
333 template<class T> struct RemoveConst<const T> { typedef T Type; };
337 template<class T> struct RemoveVolatile { typedef T Type; };
339 template<class T> struct RemoveVolatile<volatile T> { typedef T Type; };
343 template<class T> struct RemoveConstVol { typedef T Type; };
345 template<class T> struct RemoveConstVol<const T> { typedef typename RemoveConstVol<T>::Type Type; };
346 template<class T> struct RemoveConstVol<volatile T> { typedef typename RemoveConstVol<T>::Type Type; };
350 template<class T> struct RemoveExtents { typedef T Type; };
352 template<class T> struct RemoveExtents<T*> { typedef typename RemoveExtents<T>::Type Type; };
353 template<class T> struct RemoveExtents<T[]> { typedef typename RemoveExtents<T>::Type Type; };
354 template<class T, ulong N> struct RemoveExtents<T[N]> { typedef typename RemoveExtents<T>::Type Type; };
359 
361 
363 template<class T> struct ToSigned { typedef T Type; };
365 template<> struct ToSigned<unsigned char> { typedef char Type; };
366 template<> struct ToSigned<unsigned short> { typedef short Type; };
367 template<> struct ToSigned<unsigned int> { typedef int Type; };
368 template<> struct ToSigned<unsigned long> { typedef long Type; };
369 template<> struct ToSigned<unsigned long long> { typedef long Type; };
373 template<class T> struct ToUnsigned { typedef T Type; };
375 template<> struct ToUnsigned<signed char> { typedef unsigned char Type; };
376 template<> struct ToUnsigned<char> { typedef unsigned char Type; };
377 template<> struct ToUnsigned<short> { typedef unsigned short Type; };
378 template<> struct ToUnsigned<int> { typedef unsigned int Type; };
379 template<> struct ToUnsigned<long> { typedef unsigned long Type; };
380 template<> struct ToUnsigned<long long> { typedef unsigned long long Type; };
383 
392 #define EVO_TRAIT_CREATE(Name) template<class T> struct Name : StaticBoolF { };
393 
416 #define EVO_TRAIT_SET(Name,Type) template<> struct Name< Type > : public StaticBoolT { };
417 
443 #define EVO_TRAIT_NSET(Namespace,Name,Type) namespace Namespace { template<> struct Name< Type > : public StaticBoolT { }; }
444 
446 
451 
452 
459 #define EVO_CONTAINER(Type) EVO_TRAIT_NSET(evo,EvoContainer,Type)
460 
482 #define EVO_CONTAINER_TYPE typedef void EvoContainerType
483 
485 
487 // Applies (calls) f(type) for each builtin type
488 #define EVO_APPLY_BUILTINS(f) \
489  f(bool); \
490  f(char); \
491  f(signed char); \
492  f(unsigned char); \
493  f(short); \
494  f(unsigned short); \
495  f(int); \
496  f(unsigned int); \
497  f(long); \
498  f(unsigned long); \
499  f(long long); \
500  f(unsigned long long); \
501  f(float); \
502  f(double); \
503  f(long double);
504 
505 // PodType & ByteCopyType
506 template<class T> struct PodType : StaticBoolF { };
507 template<class T> struct ByteCopyType : StaticBoolF { };
508 #define EVO_PODTYPE(Type) template<> struct PodType<Type> : public StaticBoolT { };
509 EVO_APPLY_BUILTINS(EVO_PODTYPE);
510 #undef EVO_PODTYPE // redefined below
511 
528 template<class T> struct IsPodType :
529  public StaticBool<IsPointer<T>::value || PodType<typename RemoveExtentsConstVol<T>::Type>::value> { };
530 
546 template<class T> struct IsByteCopyType :
547  public StaticBool<IsPodType<T>::value || ByteCopyType<typename RemoveExtentsConstVol<T>::Type>::value> { };
548 
564 template<class T> struct IsNormalType : public StaticBool<!IsByteCopyType<T>::value> { };
565 
567 
574 template<class T> class IsEvoContainer {
575  template<class U> struct SFINAE { };
576  template<class U> static char Test(SFINAE<typename U::EvoContainerType>*);
577  template<class U> static long Test(...);
578 public:
580  static const bool value = (!IsPodType<T>::value && (sizeof(Test<T>(0)) == sizeof(char) || EvoContainer<T>::value));
581 };
582 
584 
591 template<class T> class IsNullable {
592  template<class U> struct SFINAE { };
593  template<class U> static char Test(SFINAE<typename U::EvoNullableType>*);
594  template<class U> static long Test(...);
595 public:
596  typedef IsNullable<T> Type;
597  static const bool value = (!IsPodType<T>::value && sizeof(Test<T>(0)) == sizeof(char)) || IsEvoContainer<T>::value;
598 };
599 
601 namespace impl {
602  template<class T, bool P=IsPointer<T>::value, bool N=IsNullable<T>::value>
603  struct IsNull {
604  static bool check(const T&)
605  { return false; }
606  };
607  template<class T> struct IsNull<T,true,false> {
608  static bool check(const T val)
609  { return (val == NULL); }
610  };
611  template<class T> struct IsNull<T,false,true> {
612  static bool check(const T& val)
613  { return val.null(); }
614  };
615 }
631 template<class T>
632 inline bool is_null(const T& val)
633  { return impl::IsNull<T>::check(val); }
634 
636 
697 struct TypeId {
699  struct Pod { };
700 
702  struct ByteCopy { };
703 
705  struct Normal { };
706 
708  enum Enum {
709  POD = 0,
711  NORMAL
712  };
713 
720  template<class T> struct Get {
722  typedef typename StaticIf<IsPodType<T>::value, Pod,
724  >::Type Id;
725 
727  static const Enum ENUM = (IsPodType<T>::value ? POD : (IsByteCopyType<T>::value ? BCOPY : NORMAL));
728  };
729 
736  template<class T> struct GetFill {
740  Normal
741  >::Type Id;
742 
744  static const Enum ENUM = (IsPodType<T>::value ? POD : (IsByteCopyType<T>::value ? BCOPY : NORMAL));
745  };
746 };
747 
764 #define EVO_PODTYPE(Type) namespace evo { template<> struct PodType<Type> : public StaticBoolT { }; }
765 
780 #define EVO_BCTYPE(Type) namespace evo { template<> struct ByteCopyType<Type> : public StaticBoolT { }; }
781 
791 #define EVO_TYPE_SELECT(T,Pod,Bc,Normal) typename StaticIf<IsPodType<T>::value,Pod,typename StaticIf<IsByteCopyType<T>::value,Bc,Normal>::Type>::Type
792 
794 
826 #define EVO_CREATE_HAS_VAR(TypeName, VarType, VarName) \
827  template<class T> class TypeName { \
828  template<class U, VarType U::*> struct SFINAE { }; \
829  template<class U> static char Test(SFINAE<U, &U::VarName>*); \
830  template<class U> static long Test(...); \
831  public: \
832  static const bool value = (sizeof(Test<T>(0)) == sizeof(char)); \
833  }
834 
868 #define EVO_CREATE_HAS_METHOD(TypeName, ReturnType, Func, ...) \
869  template<class T> class TypeName { \
870  template<class U, ReturnType (U::*)(__VA_ARGS__)> struct SFINAE { }; \
871  template<class U> static char Test(SFINAE<U, &U::Func>*); \
872  template<class U> static long Test(...); \
873  public: \
874  static const bool value = (sizeof(Test<T>(0)) == sizeof(char)); \
875  }
876 
910 #define EVO_CREATE_HAS_METHOD_CONST(TypeName, ReturnType, Func, ...) \
911  template<class T> class TypeName { \
912  template<typename U, ReturnType (U::*)(__VA_ARGS__) const> struct SFINAE { }; \
913  template<typename U> static char Test(SFINAE<U, &U::Func>*); \
914  template<typename U> static long Test(...); \
915  public: \
916  static const bool value = (sizeof(Test<T>(0)) == sizeof(char)); \
917  }
918 
920 
921 // ContainerType trait (used internally)
923 template<class T> struct ContainerType : StaticBoolF { };
924 #define EVO_CONTAINERTYPE(Type) template<> struct ContainerType<Type> : public StaticBoolT { };
925 
927 
929 }
930 #endif
Remove const from type.
Definition: meta.h:331
Check if type is a normal type (not POD and not ByteCopy type).
Definition: meta.h:564
Check if type is an EvoContainer.
Definition: meta.h:574
Static bool value.
Definition: meta.h:111
Static conditional type.
Definition: meta.h:134
evo::StaticBool< val > Type
This type.
Definition: meta.h:112
StaticBool< false > StaticBoolF
Static bool value (false).
Definition: meta.h:117
Remove extents (pointer and array parts) and then const & volatile from type.
Definition: meta.h:358
Translate integer type to unsigned.
Definition: meta.h:373
Evo implementation detail for system portability – this is included by most Evo headers, include this via: include <evo/type.h>.
Byte-copy type ID value.
Definition: meta.h:710
const T Type
Translated type.
Definition: meta.h:325
T Type
Translated type.
Definition: meta.h:337
Check if type is a Plan Old Data type.
Definition: meta.h:528
T Type
Translated type.
Definition: meta.h:350
Check if type is const.
Definition: meta.h:215
T Type
Translated type.
Definition: meta.h:331
bool is_null(const T &val)
Check whether object or value is null.
Definition: meta.h:632
T Type
Translated type.
Definition: meta.h:373
Use to get type ID info for type T as for filling arrays/buffers.
Definition: meta.h:736
IsEvoContainer< T > Type
This type.
Definition: meta.h:579
Translate integer type to signed.
Definition: meta.h:363
Remove const & volatile from type.
Definition: meta.h:343
T Type
Translated type.
Definition: meta.h:363
Used to identify ByteCopy types.
Definition: meta.h:702
#define EVO_PODTYPE(Type)
Identify given type as a Plain Old Data Type.
Definition: meta.h:764
Remove volatile from type.
Definition: meta.h:337
Trait to identify Evo container types.
Definition: meta.h:450
Check if type T is convertible to type U.
Definition: meta.h:310
Evo C++ Library namespace.
Definition: alg.h:11
T Type
Result type (T or F)
Definition: meta.h:134
Type ID info (POD, ByteCopy, Normal).
Definition: meta.h:697
Remove extents (pointer and array parts) from type.
Definition: meta.h:350
#define EVO_TRAIT_CREATE(Name)
Helper for creating a boolean trait type.
Definition: meta.h:392
Enum
Type ID enum values.
Definition: meta.h:708
StaticIf< IsPodType< T >::value||IsByteCopyType< T >::value, typename StaticIf< sizeof(T)==1, Pod, ByteCopy >::Type, Normal >::Type Id
Type ID for type T (Pod for memset, ByteCopy for memcpy, Normal for assignment).
Definition: meta.h:741
StaticIf< IsPodType< T >::value, Pod, typename StaticIf< IsByteCopyType< T >::value, ByteCopy, Normal >::Type >::Type Id
Type ID for type T (Pod, ByteCopy, Normal).
Definition: meta.h:724
Check if type is a floating point type.
Definition: meta.h:277
IsNullable< T > Type
This type.
Definition: meta.h:596
Check if integer type is unsigned.
Definition: meta.h:296
T Type
Translated type.
Definition: meta.h:343
Check if type is a pointer.
Definition: meta.h:168
Used to identify normal types (not POD, and not ByteCopy).
Definition: meta.h:705
Used to identify POD (Plain Old Data) types.
Definition: meta.h:699
Check if type is a ByteCopy type.
Definition: meta.h:546
Check if types are exactly the same.
Definition: meta.h:152
StaticBool< true > StaticBoolT
Static bool value (true).
Definition: meta.h:120
Check if type is nullable.
Definition: meta.h:591
Check if type is a reference.
Definition: meta.h:199
Check if type is an integer (whole number) type.
Definition: meta.h:248
RemoveConstVol< typename RemoveExtents< T >::Type >::Type Type
Translated type.
Definition: meta.h:358
Check if type is a boolean (true/false) type.
Definition: meta.h:229
Add const to type.
Definition: meta.h:325
Use to get type ID info for type T.
Definition: meta.h:720
Check if type is an array.
Definition: meta.h:183