I've been experimenting with variadic templates and argument forwarding. I think I've found some inconsistent behaviour.
To illustrate, this program:
#include <iostream>
#include <typeinfo>
#include <tuple>
#include <cxxabi.h>
template <typename... Args> struct X {};
struct A {
A () {}
A (const A &) {
std :: cout << "copy\n";
}
};
template <typename T> const char * type_name () {
return abi :: __cxa_demangle (typeid (T) .name (), 0, 0, NULL);
}
void foo () {}
template <typename... Args>
void foo (const A &, Args ... args) {
std :: cout << type_name <X <Args...>> () << "\n“; foo (args...);
}
int main () {
foo (A(), A());
}
Outputs the following:
X<A, A>
copy
X<A>
Even though the template specialisation of foo has a const reference first argument, the variadic arguments are passed by value because the template types are deduced as non-reference types, as the X<A> output indicates.
So, I consult Thomas Becker:
template<typename T> void foo(T&&);Here, the following apply:
When foo is called on an lvalue of type A, then T resolves to A& and hence, by the reference collapsing rules above, the argument type effectively becomes A&.
When foo is called on an rvalue of type A, then T resolves to A, and hence the argument type becomes A&&.
And try this:
template <typename... Args>
void foo (const A &, Args && ... args) {
std :: cout << type_name<X<Args...>>() << "\n";
foo (args...);
}
Which outputs:
X<A, A>
X<A&>
Now I'm stumped. There are three invocations of foo here. In my head, main() should deduce foo<A,A,A>(A&&,A&&,A&&) (because A() is an unnamed rvalue, hence a reference) which overload-resolves to foo<A,A,A>(const A&,A&&,A&&). This in turn deduces foo<A,A>(A&&,A&&) and so on.
Question is: how come X<A,A> has non-reference As but X<A&> has a reference A?
This causes a problem because I can't use std::forward in the recursion.
X<A> X<>, or increasing number ofA()s inmain,X<A, A> copy X<A> X<>. It is a mystery how could you getX<A&>as the last line at all, with or without ampersand. It should beX<>regardless. - n. 1.8e9-where's-my-share m.