Here is a short program to print tuples using code adapted from answers from Johannes Schaub – litb and Luc Danton.
#include <iostream>
#include <tuple>
template<int ...>
struct seq { };
template<int N, int ...S>
struct gens : gens<N-1, N-1, S...> { };
template<int ...S>
struct gens<0, S...> {
typedef seq<S...> type;
};
template <int ...S, typename ...T>
void print(const std::tuple<T...> & tup, seq<S...> s) {
int res[] = { (std::cout << std::get<S>(tup) << " ", 0)... };
std::cout << std::endl;
}
int main() {
std::tuple<double, int, char> tup(1.5, 100, 'c');
print(tup, gens<std::tuple_size<decltype(tup)>::value >::type());
return 0;
}
The second argument of print will always be always be gens<N>::type(), where N is the size of the tuple. I am trying to eschew the second argument to print by providing a default argument:
template <int ...S, typename ...T>
void print(const std::tuple<T...> & tup, seq<S...> s = gens<std::tuple_size<decltype(tup)>::value >::type()) {
int res[] = { (std::cout << std::get<S>(tup) << " ", 0)... };
std::cout << std::endl;
}
However, the result is a compiler error:
tmp5.cpp: In function ‘void print(const std::tuple<_Elements …>&, seq) [with int …S = {}; T = {double, int, char}]’:
tmp5.cpp:23:12: error: incomplete type ‘std::tuple_size&>’ used in nested name specifier
Do you know of any way to provide S... without the second argument to functions like print?
No, there is not.
As a matter of fact, this issue is not restricted to variadic template, it occurs for all template functions: the template type of an argument cannot be deduced from its default value.
You need to switch gears.
The easiest way to do so would be to provide an overload that would be tasked with passing the second argument. After all, default arguments are just syntactic sugar to avoid writing a forwarding function.