给定这段代码,模板参数推导如何决定对最后一个函数调用执行什么操作?
#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)看起来很简单。它不能推导出返回类型,所以使用void
版本。
(2)显式声明一些参数的类型。第一个模板参数与第一个参数匹配,第二个模板参数与第二个参数匹配,第三个模板参数被推导出来。如果将int
用于返回类型,则char
将与第一个参数不匹配。
(3)做与(2)相同的事情,但第一个类型不匹配。因此,必须将其推导为返回类型和用于推导两个Args
参数的两个参数。
(4)似乎模棱两可。它显式地指定一个模板参数,就像(2)和(3)一样。模板参数与参数匹配,就像(2)一样。但是,它不会将其用作第一个参数并推导出其他两个参数,而是使用显式模板参数作为返回类型,并推导出所有三个Args
参数。
为什么(4)看起来跟了(2)一半,然后又用了另一个版本?我最好的猜测是,正在填充的单个模板参数比参数包更匹配。标准在哪里定义了这种行为?
这是用GCC 4.8.0编译的。为了方便起见,这里有一个Coliru上的test run。
然而,在Clang 3.1上,(4)由于不明确而无法编译(请参阅注释)。这打开了这两个编译器中有一个有bug的可能性。使这种可能性更大的是这样一个事实,即Visual Studio 2012年11月的CTP编译器给出了与Clang相同的结果,但(4)是不明确的。
https://stackoverflow.com/questions/16409588
复制相似问题