Use default template parameter of one template declaration in another

Viewed 58

Let's assume I have a class template cls1 with some default template arguments and another class template cls2 that uses cls1:

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

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

Now, if I wanted to change the default of some of cls1's template argument, I'd also need to manually change it in cls2 for consistency.

I've already thought about using a type alias (or constexpr variable in the case of non-type template arguments):

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 T2 = cls1_default_t_2, typename U = cls1_default_u_t<T1>>
class cls2 : public cls1<T1, T2, U> {};

Now I only need to change cls1_default_t_2 or cls1_default_u.

However, this is kinda verbose depending on the number of default arguments. Additionally, if I now wanted to make another class template cls3 use cls2, it'd be unfavorable to use cls1's default arguments, since cls1 is actually not directly used by cls3. Instead I'd again need to provide type alises (and constexprs) for the default template argments of cls2, to use them in 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, T2, U> {};

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

So, is there a more concise notation to use default template arguments of one template declaration in another?

1 Answers

I dont think there is a way to avoid verbosity completely. Similar to function default arguments, you can't really get your hands on templates default arguments without some added effort. This is the best I can come up with:

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> {};

Having the aliases can be beneficial not only for default parameters, so maybe this isn't really "extra" effort.

Note that container_type is std::vector<int> not a tempalte <typename T> std::vector<T> as you asked for. You would need to write a small helper if that is needed.

Related