Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 846
Pradhan Avatar asked Nov 24 '25 00:11

Pradhan


1 Answers

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.

like image 146
Johannes Schaub - litb Avatar answered Nov 26 '25 20:11

Johannes Schaub - litb



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!