Given this code, how does template argument deduction decide what to do for the last function call?
#include <iostream>
template<typename Ret, typename... Args>
Ret foo(Args&&...) {
std::cout << "not void\n";
return {};
}
template<typename... Args>
void foo(Args&&...) {
std::cout << "void\n";
}
int main() {
foo(3, 'a', 5.4); //(1): prints "void"
foo<int, char>(3, 'a', 5.4); //(2): prints "void"
foo<int>('a', 5.4); //(3): prints "not void"
foo<int>(3, 'a', 5.4); //(4): prints "not void"
}
(1) seems pretty straightforward. It can't deduce a return type, so the void
version is used.
(2) explicitly states some of the arguments' types. The first template argument matches the first argument, the second template argument matches the second argument, and the third template argument is deduced. If the int
was used for the return type, the char
wouldn't match the first argument.
(3) does the same thing as (2), but the first types do not match. Therefore, that must be deduced as the return type and the two arguments used to deduce the two Args
arguments.
(4) seems ambiguous. It explicitly specifies a template argument, just like (2) and (3). The template argument matches the argument, just like (2). However, it does not use that as the first and deduce the other two, but rather use the explicit template argument as the return type and deduce all three Args
arguments.
Why does (4) seem to half follow (2), but then use the other version? The best guess I have is that the single template parameter being filled in is a better match than just the parameter pack. Where does the standard define this behaviour?
This was compiled using GCC 4.8.0. For convenience, here's a test run on Coliru.
On Clang 3.1, however, (4) does not compile, due to ambiguity (see comments). This opens up the possibility that one of these two compilers has a bug. Making this possibility more probable is the fact that the Visual Studio 2012 November CTP compiler gives the same result as Clang, with (4) being ambiguous.