Best way (Or workaround) to specialize a template alias

c++, c++11, template-aliases, template-meta-programming, template-specialization

Solution

The pattern I use to specialize template aliases (or provide recursive aliases) is to have a corresponding _impl struct. For example:

template <typename T>
struct my_alias_impl { /* def'n */ };

template <>
struct my_alias_impl<int> { /* alternate def'n */ };

template <typename T>
using my_alias = my_alias_impl<T>;

Users would have to specialize on my_alias_impl instead, but the rest of the public interface remains clean.

Problem

I'm currently implementing a tiny metaprogramming-based compile-time computations library. If have defined a base class for operators, which has a result typedef (I have decided to use integral wrappers like `std::integral_constant` as values instead of raw integral values, to provide an uniform interface along the library), and a n-ary operator base class, that checks if the operators has at least one operand: ``` template<typename RESULT> struct operator { using result = RESULT; }; template<typename RESULT , typename... OPERANDS> struct nary_operator : public operator<RESULT> { static_assert( sizeof... OPERANDS > 0 , "An operator must take at least one operand" ); }; ``` So I defined alias for unary and binary operators: ``` template<typename OP , typename RESULT> using unary_operator = nary_operator<RESULT , OP>; template<typename LHS , typename RHS , typename RESULT> using binary_operator = nary_operator<RESULT , LHS , RHS>; ``` That operator interfaces are used to define custom operators as alias, like comparison operators below: ``` template<typename LHS , typename RHS> using equal = binary_operator<LHS,RHS,bool_wrapper<LHS::value == RHS::value>>; template<typename LHS , typename RHS> using not_equal = logical_not<equal<LHS,RHS>>; template<typename LHS , typename RHS> using less_than = binary_operator<LHS,RHS,bool_wrapper<LHS::value < RHS::value>>; template<typename LHS , typename RHS> using bigger_than = less_than<RHS,LHS>; template<typename LHS , typename RHS> using less_or_equal = logical_not<bigger_than<LHS,RHS>>; template<typename LHS , typename RHS> using bigger_or_equal = logical_not<less_than<LHS,RHS>>; ``` Now suppose we want to implement our custom equality operator for our own class. For example: ``` template<typename X , typename Y , typename Z> struct vec3 { using x = X; using y = Y; using z = Z; }; ``` If the equality operator was made upon inheritance, instead of aliasing, this could be easily done through template specialization: ``` //Equality comparator implemented through inheritance: template<typename LHS , typename RHS> struct equal : public binary_operator<LHS,RHS,bool_wrapper<LHS::value == RHS::value>> {}; //Specialization of the operator for vec3: template<typename X1 , typename Y1 , typename Z1 , typename X2 , typename Y2 , typename Z2> struct equal<vec3<X1,Y1,Z1>,vec3<X2,Y2,Z2>> : public binary_operator<vec3<X1,Y1,Z1>,vec3<X2,Y2,Z2> , bool_wrapper<X1 == X2 && Y1 == Y2 && Z1 == Z2>> {}; ``` I know that template alias cannot be specialized. My question is: Is there a way, that is not to use inheritance design instead of template aliases, to specialize this kind of template aliases?

Original source

Related problems