在可变参数函数模板f()中,由于[temp.dep],递归调用中的f是一个依赖名称,强调我的:
在一个表达式中
形式:
postfix-expression ( expression-listopt)
如果后缀表达式是一个unqualified-id,unqualified-id表示一个从属名称如果
(1.1) — 表达式列表 中的任何表达式都是包扩展 (14.5.3),
并且,根据 [temp.dep.res],强调我的:
在解析从属名称时,会考虑以下来源的名称:
(1.1) — 在模板的定义点可见的声明。
(1.2) — 来自与函数参数类型相关的命名空间的声明
实例化上下文 (14.6.4.1) 和定义上下文。
只有一个f 声明在template <typename... Args> void f(int, int, Args...) 的定义点可见,这就是它本身。第二点在这里不适用,因为您的所有参数都是ints,并且基本类型没有关联的命名空间。由于无法使用单个参数调用该函数模板,因此会出现编译错误。
解决方案是重构你的代码,使你的基本情况在定义点可见,即:
// this can be just the declaration
void f(int, int ) { /* ... */ }
template <typename... Args>
void f(int a, int b, Args... args)
{
std::cout << b << '\n';
f(a, args...); // now this will call f(int, int)
// if sizeof...(Args) == 1
}
适用 (1.2) 的示例如下:
#include <iostream>
template <typename A, typename... Args>
void f(A a, int b, Args... args) {
std::cout << b << '\n';
f(a, args...);
}
template <typename A>
void f(A a, int b) {
std::cout << b << '\n';
}
struct bar {};
int main() {
//f(1,2,3); // still doesn't compile, same reasoning
f(bar{}, 2, 3); // OK. bar is in the global namespace, so declarations
// from the global namespace in both instantiation
// and definition context are considered, which includes
// the second `f`.
}