The question is, why it doesn't work if tuple is not at the first position of its parent. Looks like it doesn't see overload for tuple from inside _after_print.
_print(make_tuple(), 0);
Evaluates to this:
a tuple
not a tuple
And
_print(0, make_tuple());
Gives this:
not a tuple
not a tuple
template <typename _First, typename ..._Vals>
void _print(_First&& first, _Vals... _vals)
{
cout << "not a tuple" << endl;
_after_print(_vals...);
}
template <typename ..._List, typename ..._Vals>
void _print(tuple<_List...>&& t, _Vals... _vals)
{
cout << "a tuple" << endl;
_after_print(_vals...);
}
void _print() {}
template <typename ..._Vals>
void _after_print(_Vals... _vals)
{
_print(_vals...);
}
Your issue is here:
template <typename ..._List, typename ..._Vals>
void _print(tuple<_List...>&& t, _Vals... _vals)
// ^^
I assume that you wanted to use perfect forwarding, but that unconditionally names an rvalue reference; reference collapsing rules do not apply there. The dead-simple fix is to declare it as const tuple<_List...>& instead, but if you want to use perfect forwarding, you'll need to do something like this:
//trait to check if a type is a std::tuple instantiation
template <typename T>
struct is_tuple : std::false_type{};
template <typename... Ts>
struct is_tuple<std::tuple<Ts...>> : std::true_type{};
//base case
void printImpl(char) {}
//forward declaration
template <typename First, typename ...Vals>
void printImpl(char,First&& first, Vals&&... vals);
//enabled when the first is a tuple
template <typename Tuple, typename ...Vals,
typename std::enable_if<is_tuple<typename std::decay<Tuple>::type>::value>::type* = nullptr>
void printImpl(int, Tuple&& t, Vals&&... vals)
{
cout << "a tuple" << endl;
printImpl(0,std::forward<Vals>(vals)...);
}
//first is not a tuple
template <typename First, typename ...Vals>
void printImpl(char,First&& first, Vals&&... vals)
{
cout << "not a tuple" << endl;
printImpl(0,std::forward<Vals>(vals)...);
}
//helper to fill in the disambiguating argument
template <typename... Ts>
void print(Ts&&... ts)
{
printImpl(0,std::forward<Ts>(ts)...);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With