Search code examples
c++templatesoperator-overloadingtemplate-specializationpartial-specialization

Partial class template specialisation for multiple types


I have a class which allows for a vector to be created holding any type or class. However I'd like to add additional functionality for numerical types.

template <>
class Vec<double> : public VecBase<double>
{
    //  == METHODS ==
    public:
        //  -- Constructors & Destructors --
        explicit Vec(const unsigned long long t_size);
        virtual ~Vec();

        //  -- Operators --
        friend Vec<double> operator+(const Vec<double>&, const double);

        //  -- Methods --
        double sum();

... etc.

I have partially specialised the class template to allow overloading of mathematical operators for double specialisation. I'd now like to extend this specialisation to int as well, but rather than copy the specialisation replacing double with int, is there a way to add it into the specialisation list?

That is, is there any way to allow for:

template<>
class Vec<double (or) int>

Cheers!


Solution

  • I suppose you can use a boolean default value, like in foo struct in the following example

    #include <iostream>
    
    template <typename>
    struct isSpecialType
     { static constexpr bool value { false }; };
    
    template <>
    struct isSpecialType<int>
     { static constexpr bool value { true }; };
    
    template <>
    struct isSpecialType<double>
     { static constexpr bool value { true }; };
    
    template <typename T, bool = isSpecialType<T>::value>
    struct foo;
    
    template <typename T>
    struct foo<T, true>
     { static constexpr bool value { true }; };
    
    template <typename T>
    struct foo<T, false>
     { static constexpr bool value { false }; };
    
    int main()
     {
       std::cout << "- void value:   " << foo<void>::value << std::endl;
       std::cout << "- bool value:   " << foo<bool>::value << std::endl;
       std::cout << "- int value:    " << foo<int>::value << std::endl;
       std::cout << "- double value: " << foo<double>::value << std::endl;
     }
    

    The idea is define a sort of type traits (isSpecialType) to choose the selected types (int and double, in your example) with a booleand value that is false in the generic implementation and true in the specializations.

    template <typename>
    struct isSpecialType
     { static constexpr bool value { false }; };
    
    template <>
    struct isSpecialType<int>
     { static constexpr bool value { true }; };
    
    template <>
    struct isSpecialType<double>
     { static constexpr bool value { true }; };
    

    Next you have to declare the foo struct (class Vec, in your question) with a supplemental bool template value with the isSpecialType<T>::value default value

    template <typename T, bool = isSpecialType<T>::value>
    struct foo;
    

    Last, you have to implement two partially specialized version of foo: the first one with the boolean true value

    template <typename T>
    struct foo<T, true>
     { static constexpr bool value { true }; };
    

    corresponding to the specialized version of your Vec; the one with the false boolean value

    template <typename T>
    struct foo<T, false>
     { static constexpr bool value { false }; }; 
    

    corresponding to the generic version of your Vec.

    Another point: my example is C++11 or newer code; if you want a C++98 version, you have only to define the bool values as const (instead constexpr) and initialize they whit the C++98 style; I mean

     static bool const bool value = true;
    

    instead of

     static constexpr bool value { true };