PVData C++  8.0.5
templateMeta.h
1 /*
2  * Copyright information and license terms for this software can be
3  * found in the file LICENSE that is included with the distribution
4  */
5 /** C++ Template meta programming helpers
6  */
7 #ifndef TEMPLATEMETA_H
8 #define TEMPLATEMETA_H
9 
10 // gently nudge the compiler to inline our wrappers
11 // Warning: Only use this when the template body is *small*.
12 // You have been warned!
13 #if defined(__MINGW32__)
14 # define FORCE_INLINE inline
15 #elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 402)
16 # define FORCE_INLINE __attribute__((always_inline)) inline
17 #elif defined(_MSC_VER)
18 # define FORCE_INLINE __forceinline
19 #else
20 # define FORCE_INLINE inline
21 #endif
22 
23 namespace epics { namespace pvData {
24 namespace meta {
25 
26 /** If needed, add the 'const' qualifier to the provided type.
27  *
28  * Avoids adding the const qualifier twice (aka 'const const int')
29  @code
30  assert(typeid(decorate_const<int>::type)==typeid(const int));
31  assert(typeid(decorate_const<const int>::type)==typeid(const int));
32  @endcode
33  */
34 template<typename T> struct decorate_const { typedef const T type; };
35 template<typename T> struct decorate_const<const T> { typedef const T type; };
36 
37 /** Remove the 'const' qualifier if present
38  @code
39  assert(typeid(strip_const<int>::type)==typeid(int));
40  assert(typeid(strip_const<const int>::type)==typeid(int));
41  @endcode
42  */
43 template<typename T> struct strip_const { typedef T type; };
44 template<typename T> struct strip_const<const T> { typedef T type; };
45 
46 /** test to allow specialization only when A!=B
47  *
48  @code
49  template<typename A, typename B, class Enable = void>
50  struct myTemp {...};
51 
52  // specialization when A==B
53  template<typename T>
54  struct myTemp<T,T> {...};
55 
56  // specialization for A is 'int',
57  // enabler needed to remove ambiguity when B is 'int'.
58  template<typename B>
59  struct myTemp<int, B, typename meta::not_same_type<int,B>::type>
60  {...};
61  @endcode
62  */
63 template<typename A, typename B, typename R = void>
64 struct not_same_type {typedef R type;};
65 template<typename A>
66 struct not_same_type<A,A> {};
67 
68 //! Select if both A and B have the same root type (excluding const qualifier)
69 template<typename A, typename B, class R = void> struct same_root {};
70 template<typename T, class R> struct same_root<T,T,R> { typedef R type; };
71 template<typename T, class R> struct same_root<const T,T,R> { typedef R type; };
72 template<typename T, class R> struct same_root<T,const T,R> { typedef R type; };
73 
74 namespace detail {
75  struct _const_yes {};
76  struct _const_no {};
77  template<typename T> struct _has_const { typedef _const_no type; };
78  template<typename T> struct _has_const<const T> { typedef _const_yes type; };
79 
80  template<typename A, typename B, class R = void> struct _same_type {};
81  template<typename T, class R> struct _same_type<T,T,R> { typedef R type; };
82 } // namespace detail
83 
84 //! Check if both A and B are either const or non-const.
85 template<typename A, typename B, class R = void>
86 struct same_const :
87  public detail::_same_type<typename detail::_has_const<A>::type,
88  typename detail::_has_const<B>::type,
89  R>
90 {};
91 
92 /** test if provided type is 'void' or 'const void'
93  *
94  * Avoid having to explicitly specialize for both
95  @code
96  template<typename A, class Enable = void>
97  struct myTemp {...};
98 
99  // specialization when A is 'void' or 'const void'
100  template<typename A>
101  struct myTemp<A, typename meta::is_void<A>::type> {...};
102  @endcode
103  */
104 template<typename T, class R = void> struct is_void {};
105 template<class R> struct is_void<void,R> { typedef R type; };
106 template<class R> struct is_void<const void,R> { typedef R type; };
107 
108 //! Inverse of is_void<T>
109 template<typename T, class R = void> struct is_not_void { typedef R type; };
110 template<> struct is_not_void<void> {};
111 template<> struct is_not_void<const void> {};
112 
113 //! Enabler to ensure that both conditions A and B are true
114 template<typename A, typename B, class EnableA = void, class EnableB = void, class R = void>
115 struct _and {};
116 template<typename A, typename B, class R>
117 struct _and<A,B, typename A::type, typename B::type, R> { typedef R type; };
118 
119 /** Mangle type to best pass as an argument.
120  *
121  * POD types passed by value.
122  * All others by const reference.
123  */
124 template<typename T>
125 struct arg_type {typedef const T& type;};
126 #define SIMPLE_ARG_TYPE(TYPE) template<> struct arg_type<TYPE> { typedef TYPE type; };
129 SIMPLE_ARG_TYPE(signed char)
130 SIMPLE_ARG_TYPE(unsigned char)
132 SIMPLE_ARG_TYPE(unsigned short)
134 SIMPLE_ARG_TYPE(unsigned int)
136 SIMPLE_ARG_TYPE(unsigned long)
137 SIMPLE_ARG_TYPE(long long)
138 SIMPLE_ARG_TYPE(unsigned long long)
141 SIMPLE_ARG_TYPE(long double)
142 #undef SIMPLE_ARG_TYPE
143 
144 }}}
145 
146 #endif // TEMPLATEMETA_H
Inverse of is_void<T>
Definition: templateMeta.h:109
Select if both A and B have the same root type (excluding const qualifier)
Definition: templateMeta.h:69
#define SIMPLE_ARG_TYPE(TYPE)
Definition: templateMeta.h:126
Check if both A and B are either const or non-const.
Definition: templateMeta.h:86
virtual void serialize(ByteBuffer *buffer, SerializableControl *flusher, std::size_t offset, std::size_t count) const =0
Enabler to ensure that both conditions A and B are true.
Definition: templateMeta.h:115