由于8.3.6 ([dcl.fct.default])/4,
在给定的函数声明中,带有默认实参的形参后面的每个形参都应具有在此声明或先前声明中提供的默认实参,或者应为函数形参包。
以下应编译:
#include <iostream>
template<typename ...Ts>
void foo(int i=8, Ts... args)
{
std::cout << "Default parameters \t= " << i << "\n";
std::cout << "Additional params \t= " << sizeof...(Ts) << "\n";
}
int main()
{
foo(); // calls foo<>(int)
foo(1, "str1", "str2"); // calls foo<const char*, const char*>(int, const char*, const char*)
foo("str3"); // ERROR: does not call foo<const char*>(int, const char*)
return 0;
}
但它不会编译,因为foo("str3")
这会使编译器感到困惑。它抱怨没有匹配的调用函数,foo(const char*)
并且它无法将"str3"
(type const char*
) 转换为 type int
。
我知道可以通过函数重载或使用命名参数习语来解决这个问题(参见在哪里将默认值参数放置在 c++ 中的可变长度函数中?以及默认参数和可变参数函数)。但是,我想知道编译器是否只是愚蠢的,或者是否有真正的原因导致上面代码示例中的预期行为没有实现。换句话说,即使我将函数显式实例化为,为什么编译器会抱怨foo<const char*>(int, const char*)
?就好像显式实例化只是忽略了默认参数的值。为什么?