Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making a tuple-like compile-time "linked-list" with variadic templates

I was pondering possible implementations of std::tuple (and any similar template classes with a variable number of "members" defined at compile time), and I thought perhaps one could create a "recursive type" resembling a linked list. I tried compiling the following test-case:

template <typename FirstType, typename... OtherTypes>
class TupleLite
{
  public:
    FirstType type_;
    TupleLite<OtherTypes...> other_types_;
};

int main()
{
  TupleLite<int,double> mytuple;
}

The class itself compiles without error, but the instantiation throws the error wrong number of template arguments (0, should be 1 or more). I believe this is because TupleLite<int, double> tries to instantiate a TupleLite<double>, which tries to instantiate a TupleLite<>, for which there is no valid definition.

Can this "recursively sized class" be salvaged? I tried defining the "no-argument specialization" of TupleLite as follows:

template <>
class TupleLite {}

....but that doesn't seem to work, although g++ and clang++ seem to disagree on exactly why.

From g++, the most relevant errors seem to be:

error: template specifiers not specified in declaration of ‘template<class FirstType, class ... OtherTypes> class TupleLite’
  class TupleLite
        ^
error: wrong number of template arguments (0, should be 1 or more)
 TupleLite<OtherTypes...> other_types_;
                          ^

clang++, however, says:

error: extraneous 'template<>' in declaration of class 'TupleLite'
template <>
^
error: redefinition of 'TupleLite' as different kind of symbol
class TupleLite
      ^
like image 819
Kyle Strand Avatar asked Oct 19 '22 15:10

Kyle Strand


1 Answers

The primary template definition of TupleLite specifies that it requires at least one template argument, FirstType. Since that isn't what you want to express, provide a primary template defition which ends up also handling the empty case like this:

template <typename...>
class TupleLite{};

And one partial specializations:

template <typename FirstType, typename... OtherTypes>
class TupleLite<FirstType, OtherTypes...>
{
  public:
    FirstType type_;
    TupleLite<OtherTypes...> other_types_;
};

Coliru Demo.

EDIT : Thanks to Nikos for pointing out that the empty spec was not needed in this case.

like image 104
Pradhan Avatar answered Nov 15 '22 07:11

Pradhan