Consider this function template:
template
void foo (std::tuple ... x);
This invocation works:
I cannot use C++17 for this. A C++11-compatible solution is much preferred.
With C++11 is a little more complicated (no std::index_sequence
, no std::make_index_sequence
) but, if you want maintain the variadic use of tuples... that is... if you substantially want something as
foo (std::tuple ... ts)
and if you accept to call a static method of a template struct, you can define a template struct that recursively inherit itself and, recursively, define a
func ();
func (K t0);
func (K t0, K t1);
func (K t0, K t1, K t2);
where K
is your
using K = std::tuple;
The following is a full compiling C++11 example
#include
#include
using K = std::tuple;
template
struct getTypeStruct
{ using type = T; };
template
using getType = typename getTypeStruct::type;
template
struct iList;
template >
struct foo;
template
struct foo> : public foo>
{
using foo>::func;
static void func (getType ... ts)
{ std::cout << sizeof...(ts) << std::endl; }
};
template
struct foo>
{
// fake func, for recursion ground case
static void func ()
{ }
};
int main()
{
foo<>::func({1,'2',3.0}); // print 1
foo<>::func({1,'2',3.0}, {4,'5',6.0}); // print 2
foo<>::func({1,'2',3.0}, {4,'5',6.0}, {7,'8',9.0}); // print 3
}
If you can use C++14, you can use std::make_index_sequence
and std::index_sequence
and the code become a little better, IMHO
#include
#include
#include
using K = std::tuple;
template
constexpr auto getIndexSequence (std::index_sequence is)
-> decltype(is);
template
using IndSeqFrom = decltype(getIndexSequence(std::make_index_sequence{}));
template
struct getTypeStruct
{ using type = T; };
template
using getType = typename getTypeStruct::type;
template >
struct foo;
template
struct foo> : public foo
{
using foo::func;
static void func (getType ... ts)
{ std::cout << sizeof...(ts) << std::endl; }
};
template <>
struct foo<0, std::index_sequence<>>
{
static void func ()
{ std::cout << "0" << std::endl; }
};
int main()
{
foo<>::func({1,'2',3.0}); // print 1
foo<>::func({1,'2',3.0}, {4,'5',6.0}); // print 2
foo<>::func({1,'2',3.0}, {4,'5',6.0}, {7,'8',9.0}); // print 3
}
It's a pity you can't use C++17 because in you could use variadic unsing
and avoid at all recursive inheritance
#include
#include
#include
using K = std::tuple;
template
constexpr auto getIndexSequence (std::index_sequence is)
-> decltype(is);
template
using IndSeqFrom = decltype(getIndexSequence(std::make_index_sequence{}));
template
struct getTypeStruct
{ using type = T; };
template
using getType = typename getTypeStruct::type;
template >
struct bar;
template
struct bar>
{
static void func (getType ... ts)
{ std::cout << sizeof...(ts) << std::endl; }
};
template >
struct foo;
template
struct foo> : public bar...
{ using bar::func...; };
int main()
{
foo<>::func({1,'2',3.0}); // print 1
foo<>::func({1,'2',3.0}, {4,'5',6.0}); // print 2
foo<>::func({1,'2',3.0}, {4,'5',6.0}, {7,'8',9.0}); // print 3
}