Following question that was answered "typedefing" base class in templates
I reposting the question with refined conditions. As before the question is how to avoid retyping fully qualified name of inherited class type name several times in template specifications. The reason is that due to long list of arguments it is very prone to forgetting changing it in several places. The code may even compile in this case, and lead to difficult to debug errors.
Example of code to improve:
template<int Index, typename ... Rest>
struct Sequence
{
// ...
};
template<int Index, typename F, typename ... Rest>
struct Sequence<Index, F, Rest ...> : public Sequence<Index+1, Rest ...>
{
// can we improve retyping the base type definitions in ctor Sequence<Index+1, Rest ...>
Sequence(int Param):Sequence<Index+1, Rest ...>(Param)
{
}
};
Pay attention to following:
a. The class derives from the same template (same name, different arguments)
b. It calls base class constructor.
Can we define the base class name only once and reuse it during template specification coding.
There's almost always a better solution than a macro. The target of this question is very old. It seeks a pattern to overcome the lack of a base keyword in C++ language that makes recursive template programming difficult. Such quests normally result in patterns, but I don't know the name of pattern illustrated in my answer.
fundamental theorem of software engineering: All problems in computer science can be solved by another level of indirection.
In present case, indirection is inheritance:
#include <type_traits>
template<typename base>
struct recursive_base
: base{
static_assert(std::is_class<base>{});
using base::base;/*constructor inheritance*/
};
Now we can just derive from recursive_base
:
template<int Index, typename ...>
struct Sequence;
template<int Index, typename First, typename ... Rest>
struct Sequence<Index, First, Rest ...>
: public recursive_base<
Sequence<Index+1, Rest ...>>
{
Sequence(int Param)
: Sequence::recursive_base{Param}
{/*Sequence(int Param)*/};
};
template<int Index>
struct Sequence<Index>
{
Sequence(int);
};
In this pattern recursive_base
is the replacement for a macro solution. Wether or not this be a visual enhancement is subjective; but it duplicates number of template instantiations. So one downside is slight reduction in compiler performance(speed and ICE probability).
Another shortcoming would be the unlikely case when multiple inheritance with same basic template is needed. That case can be handled by defining a recursive_base_2
in a similar manor.