在另一个模板声明中使用默认模板参数

问题描述

假设我有一个带有一些认模板参数的类模板cls1和另一个使用cls2的类模板cls1

template<typename T1,typename T2 = int,typename U = std::vector<T1>>
class cls1 {};

template<typename T1,typename U = std::vector<T1>>
class cls2 : public cls1<T1,T2,U> {};

现在,如果我想更改cls1模板参数中的某些认值,则还需要手动cls2中进行更改以保持一致性。

我已经考虑过使用类型别名(对于非类型模板参数,则使用constexpr变量):

using cls1_default_t_2 = int;
template<typename T1>
using cls1_default_u = std::vector<T1>;

template<typename T1,typename T2 = cls1_default_t_2,typename U = cls1_default_u_t<T1>>
class cls1 {};

template<typename T1,typename U = cls1_default_u_t<T1>>
class cls2 : public cls1<T1,U> {};

现在,我只需要更改cls1_default_t_2cls1_default_u

但是,这有点冗长,取决于认参数的数量。另外,如果我现在想让另一个类模板cls3使用cls2,则不宜使用cls1认参数,因为实际上cls1不是直接由cls3使用。相反,我再次需要为constexpr认模板参数提供类型别名(和cls2),以便在cls3中使用它们:

// ... cls1 as seen above

using cls2_default_t_2 = cls1_default_t_2;
template<typename T1>
using cls2_default_u_t = cls1_default_u_t<T1>;

template<typename T1,typename T2 = cls2_default_t_2,typename U = cls2_default_u_t<T1>>
class cls2 : public cls1<T1,U> {};

template<typename T1,typename U = cls2_default_u_t<T1>>
class cls3 : public cls2<T1,U> {};

那么,在一个模板声明中使用认模板参数在另一个模板声明中是否有更简洁的表示法?

解决方法

我认为没有办法完全避免冗长。与函数默认参数类似,如果不付出额外的努力,就无法真正使用模板默认参数。这是我能想到的最好的方法:

template<typename T1,typename T2 = int,typename U = std::vector<T1>>
class cls1 {
    using value_type = T2;
    using container_type = U;
};

template<typename T1,typename T2 = typename cls1<T1>::value_type,typename U = typename cls1<T1>::container_type>
class cls2 : public  cls1<T1,T2,U> {};

拥有别名不仅对默认参数有好处,所以也许这并不是真正的“额外”工作。

请注意,container_type不是您要求的std::vector<int>,而是tempalte <typename T> std::vector<T>。如果需要,您将需要编写一个小助手。