Search code examples
c++templatesmetaprogrammingtemplate-meta-programming

How to recursively inherit a template class from itself? (not CRTP!)


I am going to try an interesting trick! I want to recursively build an inheritance of template classes.

I am expecting to see this:

T<int, int, int> inherits T<int,int> inherits T<int> inherits T<void>
/*Here should be specializations with void...*/

template<typename T, typename... Ts>
class ToPack : ToPack<Ts...>
{
public:
    ToPack(T t, Ts... ts) : ToPack(ts...) {}
};

template<typename T>
class ToPack<T, void> {};

 int main(void)
{
     ToPack<int, int, int> t(1, 2, 3);
}

But the problem is that when the compiler tries to instantiate T<int> it tries to unpack variadic template parameters for "parent" class and it fails, i.e.

ToPack<int> -> actually ToPack<int, void> that tries to unpack ToPack<void...>

Is it possible to solve this problem?


Solution

  • As mentioned in the comments, void is itself a type, not a placeholder for empty. What you really have is ToPack<int, int, int> -> ToPack<int, int> -> ToPack<int> -> ToPack<>. ToPack<> isn't valid since it requires at least one template parameter, so this fails to compile.

    You need to change your base case by specializing on one template parameter:

    template <typename T, typename... Ts>
    class ToPack : ToPack<Ts...> {
    public:
        ToPack(T t, Ts... ts) : ToPack<Ts...>(ts...) {}
    };
    
    template <typename T>
    class ToPack<T> {
    public:
        ToPack(T t) {}
    };