Search code examples
c++templatesc++14variadic-templatestemplate-specialization

How to specialize a template-class with doubles?


I write a template class dependent on a given type and variadic types, like so:

template<typename ConstType,typename...Inputs>
class ConstantTensor;

Then I write another class, which is generally defined in this way (assume wrong_type whatever type you want, but which is different from the following specialization ):

template<typename T>
class X{
public:
using type=wrong_type;
}

And I also have a specialization of this kind:

template<typename ConstType,typename...Inputs>
class X< ConstantTensor< ConstType ,Inputs...>>
{
public:
using type=right_type;
}

My problem is that, if I define the type ConstantTensor<ConstType,double> and then I want to use X<ConstantTensor<ConstType,double>>::type, the general case is called and not the specialization. So I obtain wrong_type instead of right_type. I guess it has to deal with the double type...Could you explain me why and how can I solve this issue? Thank you in advance.

EDIT: Here a snippet of code, I hope it works:

class Scalar
{};


template<typename ConstType,typename...Inputs>
class ConstantTensor
{
  public:    
  constexpr ConstantTensor(const Inputs&...inputs)
  {}
};

template<typename ConstType,typename...Inputs>
constexpr auto Constant(const Inputs&...inputs)
{return ConstantTensor<ConstType,Inputs...>(inputs...);}

template<typename T>
class X{
public:
using type=int;
};

template<typename ConstType,typename...Inputs>
class X<ConstantTensor<ConstType,Inputs...>>{
public:
using type=char;
};

int main()
{
constexpr auto delta=Constant<Scalar>(2.0);
using type= X<decltype(delta)>::type; // this is int not char
}

Solution

  • The problem is that

    constexpr auto delta=Constant<Scalar>(2.0);
    

    is a constexpr variable; so it's also const.

    So decltype(delta) isn't ConstantTensor<Scalar> but is a ConstantTensor<Scalar> const.

    You can verify adding const in partial specialization declaration

    template<typename ConstType,typename...Inputs>
    class X<ConstantTensor<ConstType,Inputs...> const>{ // <-- added const
    public:
    using type=char;
    };
    

    Now you get that type is char.

    -- EDIT --

    The OP asks

    Is there a short/elegant way to deal with both cases, const and non const, without duplicating the code?

    I don't know if it's elegant, but it seems to me short enough: you can use a sort of self-inheritance adding the following partial specialization.

    template <typename T>
    class X<T const> : public X<T>
     { };
    

    So X<ConstantTensor<Scalar> const> inherit from X<ConstantTensor<Scalar>>.