/** * Copyright - See the COPYRIGHT that is included with this distribution. * EPICS pvData is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. */ /** C++ Template meta programming helpers */ #ifndef TEMPLATEMETA_H #define TEMPLATEMETA_H // gently nudge the compiler to inline our wrappers // Warning: Only use this when the template body is *small*. // You have been warned! #if defined(__GNUC__) && __GNUC__>=3 # define FORCE_INLINE __attribute__((always_inline)) inline #elif defined(_MSC_VER) # define FORCE_INLINE __forceinline #else # define FORCE_INLINE inline #endif namespace epics { namespace pvData { namespace meta { /** If needed, add the 'const' qualifier to the provided type. * * Avoids adding the const qualifier twice (aka 'const const int') @code assert(typeid(decorate_const::type)==typeid(const int)); assert(typeid(decorate_const::type)==typeid(const int)); @endcode */ template struct decorate_const { typedef const T type; }; template struct decorate_const { typedef const T type; }; /** Remove the 'const' qualifier if present @code assert(typeid(strip_const::type)==typeid(int)); assert(typeid(strip_const::type)==typeid(int)); @endcode */ template struct strip_const { typedef T type; }; template struct strip_const { typedef T type; }; /** test to allow specialization only when A!=B * @code template struct myTemp {...}; // specialization when A==B template struct myTemp {...}; // specialization for A is 'int', // enabler needed to remove ambiguity when B is 'int'. template struct myTemp::type> {...}; @endcode */ template struct not_same_type {typedef R type;}; template struct not_same_type {}; //! Select if both A and B have the same root type (excluding const qualifier) template struct same_root {}; template struct same_root { typedef R type; }; template struct same_root { typedef R type; }; template struct same_root { typedef R type; }; namespace detail { struct _const_yes {}; struct _const_no {}; template struct _has_const { typedef _const_no type; }; template struct _has_const { typedef _const_yes type; }; template struct _same_type {}; template struct _same_type { typedef R type; }; } // namespace detail //! Check if both A and B are either const or non-const. template struct same_const : public detail::_same_type::type, typename detail::_has_const::type, R> {}; /** test if provided type is 'void' or 'const void' * * Avoid having to explicitly specialize for both @code template struct myTemp {...}; // specialization when A is 'void' or 'const void' template struct myTemp::type> {...}; @endcode */ template struct is_void {}; template struct is_void { typedef R type; }; template struct is_void { typedef R type; }; //! Inverse of is_void template struct is_not_void { typedef R type; }; template<> struct is_not_void {}; template<> struct is_not_void {}; //! Enabler to ensure that both conditions A and B are true template struct _and {}; template struct _and { typedef R type; }; }}} #endif // TEMPLATEMETA_H