Pradhan
Pradhan

Reputation: 16737

Error partially specializing a class template to have boost::tuple as one of the parameters

I ran into errors while partially specializing a template with boost::tuple. The same code compiled on replacing boost::tuple with std::tuple. Here's the code condensed into the part that fails to compile.

template <typename... Args>
class Test;

template <typename... Args>
class Test<std::tuple<Args...>, Args...>
{
};

template <typename... Args>
class Test<boost::tuple<Args...>, Args...>
{
};

int main()
{
  int rc;

  cout<<abi::__cxa_demangle(typeid(Test<boost::tuple<int, int>, int,int>).name(), 0, 0, &rc)<<endl;//Doesn't compile                                                           
  cout<<abi::__cxa_demangle(typeid(Test<std::tuple<int, int>, int,int>).name(), 0, 0, &rc)<<endl;//Compiles
  return 0;
}

The compile error, with g++48, is

tuplerr.cpp: In function ‘int main()’:
tuplerr.cpp:30:73: error: invalid use of incomplete type ‘class Test<boost::tuples::tuple<int, int, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type>, int, int>’
cout<<abi::__cxa_demangle(typeid(Test<boost::tuple<int, int>, int,int>).name(), 0, 0, &rc)<<endl;//Doesn't compile
                                                                     ^
tuplerr.cpp:14:7: error: declaration of ‘class Test<boost::tuples::tuple<int, int, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type>, int, int>’
class Test;

However, the specialization using std::tuple works just fine. What am I doing wrong?

Upvotes: 3

Views: 130

Answers (2)

Johannes Schaub - litb
Johannes Schaub - litb

Reputation: 506945

Try this

// used below to create a "non-deduced context"
template<typename T>
struct Id { typedef T type; };

template <typename... Args>
class Test;

template <typename... Args>
class Test<typename Id<std::tuple<Args...>>::type, Args...>
{
};

template <typename... Args>
class Test<typename Id<boost::tuple<Args...>>::type, Args...>
{
};

So that the optional parameters in boost::tuple (which have default arguments because your boost's tuple implementation uses that to simulate variadic templates) don't make the first Args... contradict with the later Args... expansion that only has the required explicitly passed arguments.

Upvotes: 5

Mike M
Mike M

Reputation: 2303

boost::tuple doesn't work with variadic templates.

See here https://stackoverflow.com/a/2709502/2524462 for a workaround.

Upvotes: 1

Related Questions