Is it possible to define the specialization of an implementation template as a typedef of another type?

I have a template template for which I want to introduce several specialized templates. These template specializations are identical to some existing types. Conceptually, I would like to implement them as aliases / typedefs.

The following code example should show what I want to do:

template<class T> class Common { /// general implementation }; class TypeZ; template<> class Common<Type1> = TypeZ; // <<< how to do this? template<> class Common<Type2> = TypeZ; template<> class Common<Type3> = TypeZ; 

Is this possible somehow in C ++ (or C ++ 11)? It would be great if I didn't have to implement Common<...> as a class that inherits TypeZ - the actual code is more complex than shown above, and inheriting TypeZ not a good idea.

+8
c ++ c ++ 11 typedef templates
source share
2 answers

Assuming that only certain Common specializations are TypeZ , then you can do:

 template<class T> class Common { struct type { /// general implementation }; }; template<> class Common<Type1> { using type = TypeZ; }; template<> class Common<Type2> { using type = TypeZ; }; template<> class Common<Type3> { using type = TypeZ; }; template<class T> using common_t = typename Common<T>::type; 

Then you use common_t<T> , not Common<T> .

To entertain the idea of โ€‹โ€‹inheritance, have you tried this?

 template<> class Common<Type1> : public TypeZ { using TypeZ::TypeZ; }; template<> class Common<Type2> : public TypeZ { using TypeZ::TypeZ; }; template<> class Common<Type3> : public TypeZ { using TypeZ::TypeZ; }; 

Then you do not need to use a nested type alias.

+9
source share

Yes, you can, using enter aliases :

 template<typename T> using Common = TypeZ; 

See the link for more examples of what is possible. using can be used anywhere in typedef , plus in template aliases like the ones above, so I recommend using using over typedef wherever you write C ++ 11.


If you need more complex matching, you can use some simple template metaprograms using std::enable_if or std::conditional in combination with std::is_same . For example, if you need to specialize in only 3 types, use this :

 #include <type_traits> class Type1 {}; class Type2 {}; class Type3 {}; class Type4 {}; class TypeZ {}; // Implementation 1 template<typename T> constexpr bool is_Type123_func() { return std::is_same<T, Type1>() || std::is_same<T, Type2>() || std::is_same<T, Type3>(); } template<typename T> using Common_byfunc = typename std::conditional<is_Type123_func<T>(), TypeZ, T>::type; static_assert(std::is_same<Common_byfunc<Type1>, TypeZ>(), ""); static_assert(std::is_same<Common_byfunc<Type2>, TypeZ>(), ""); static_assert(std::is_same<Common_byfunc<Type3>, TypeZ>(), ""); static_assert(!std::is_same<Common_byfunc<Type4>, TypeZ>(), ""); // Implementation 2 template<typename T> struct is_Type123 : public std::conditional<std::is_same<T, Type1>() || std::is_same<T, Type2>() || std::is_same<T, Type3>(), std::true_type, std::false_type>::type {}; template<typename T> using Common = typename std::conditional<is_Type123<T>::value, TypeZ, T>::type; static_assert(std::is_same<Common<Type1>, TypeZ>(), ""); static_assert(std::is_same<Common<Type2>, TypeZ>(), ""); static_assert(std::is_same<Common<Type3>, TypeZ>(), ""); static_assert(!std::is_same<Common<Type4>, TypeZ>(), ""); 

Both implementations are equivalent to the name and the fact that you must use the function call operator () or the member access element of ::value in std::conditional .

+3
source share

All Articles