从另一个函数模板中调用未声明的函数模板
Calling undeclared function template from inside another function template
我正在学习 C++ 中的模板,因此尝试了不同的示例。下面给出了一个我无法理解其输出的示例:
template<typename T> void func(T p) {
g<T>(p); //ERROR
g(p); //NO ERROR?
}
int main()
{
}
当我尝试编译上面的代码片段时,我得到 error 说:
prog.cc: In function 'void func(T)':
prog.cc:2:1: error: 'g' was not declared in this scope
2 | g<T>(p); //ERROR
| ^
prog.cc:2:4: error: expected primary-expression before '>' token
2 | g<T>(p); //ERROR
| ^
我的问题是:
- 为什么会出现这个错误?
- 为什么我只收到语句
g<T>(p);
而不是 g(p);
的错误?我认为写 g(p);
等同于 g<T>(p);
,因为由于模板参数推导,g
的模板参数将被推导为 T
.
案例一
这里我们考虑语句:g<T>(p);
template<typename T> void func(T p) {
g<T>(p); //ERROR
}
int main()
{
}
在上面的代码片段中,名称 g
是一个 不合格的从属名称 。从 source: two phase lookup:
During the first phase, while parsing a template unqualified dependent names are looked up using the ordinary lookup rules. For unqualified dependent names, the initial ordinary lookup—while not complete—is used to decide whether the name is a template.
现在让我们将其应用于语句 g<T>(p);
。在解析函数模板func
时,遇到语句g<T>(p);
。由于 g
是依赖限定名,根据上面引用的语句,使用 普通查找规则[=] 查找 名称 g
。这是为了让编译器可以决定名称 g
是否是一个模板。但是由于在这一点之前没有名为 g
的函数模板的声明,因此第一个尖括号 <
被视为 小于符号 并因此产生你提到的错误。另外,请注意 ADL 是在 第二阶段 中完成的。但要做到这一点,我们必须首先成功解析函数 func
.[source 的通用定义:C++ 模板:完整指南:第 250 页倒数第二段]
请注意,允许编译器将错误延迟到实例化,这就是为什么某些编译器可以毫无错误地编译您的代码的原因。 Demo.
案例二
这里我们考虑语句g(p);
.
template<typename T> void func(T p) {
g(p); // NO ERROR
}
int main()
{
}
在这种情况下,名称 g
也是一个 不合格的从属名称 。因此,根据我的回答开头引用的陈述,使用普通查找规则 查找 名称 g
。但是由于此时没有 g
visible 我们有一个错误。这里有两点需要注意:
- 因为这次你没有明确地(通过使用尖括号)调用
g
,所以没有 语法错误。
- 并且由于在这种情况下没有语法错误,并且在您的程序中没有 POI for
func
,所以这里没有错误可以延迟,并且程序编译正常。但是,如果您实例化 func
那么您将在实例化时收到错误提示 g
was not declared.
模板使用 Two-phase name lookup.
First, at the point of the template definition, the template is checked for syntax.
所以 g(p);
是正确的(从语法的角度来看)(假设函数 g
被 ADL 找到)。
对于 g<T>(p);
,我们有(直到 C++20):
Although a function call can be resolved through ADL even if ordinary lookup finds nothing, a function call to a function template with explicitly-specified template arguments requires that there is a declaration of the template found by ordinary lookup (otherwise, it is a syntax error to encounter an unknown name followed by a less-than character)
g<T>(p);
不正确,(仅解析为 (g < T) > p;
(T
是一种类型,因此是错误的))。
如果存在任何模板函数 g
,则 g
可能被视为模板,并且从语法的角度来看代码是正确的(即使模板参数不匹配)。
我正在学习 C++ 中的模板,因此尝试了不同的示例。下面给出了一个我无法理解其输出的示例:
template<typename T> void func(T p) {
g<T>(p); //ERROR
g(p); //NO ERROR?
}
int main()
{
}
当我尝试编译上面的代码片段时,我得到 error 说:
prog.cc: In function 'void func(T)':
prog.cc:2:1: error: 'g' was not declared in this scope
2 | g<T>(p); //ERROR
| ^
prog.cc:2:4: error: expected primary-expression before '>' token
2 | g<T>(p); //ERROR
| ^
我的问题是:
- 为什么会出现这个错误?
- 为什么我只收到语句
g<T>(p);
而不是g(p);
的错误?我认为写g(p);
等同于g<T>(p);
,因为由于模板参数推导,g
的模板参数将被推导为T
.
案例一
这里我们考虑语句:g<T>(p);
template<typename T> void func(T p) {
g<T>(p); //ERROR
}
int main()
{
}
在上面的代码片段中,名称 g
是一个 不合格的从属名称 。从 source: two phase lookup:
During the first phase, while parsing a template unqualified dependent names are looked up using the ordinary lookup rules. For unqualified dependent names, the initial ordinary lookup—while not complete—is used to decide whether the name is a template.
现在让我们将其应用于语句 g<T>(p);
。在解析函数模板func
时,遇到语句g<T>(p);
。由于 g
是依赖限定名,根据上面引用的语句,使用 普通查找规则[=] 查找 名称 g
。这是为了让编译器可以决定名称 g
是否是一个模板。但是由于在这一点之前没有名为 g
的函数模板的声明,因此第一个尖括号 <
被视为 小于符号 并因此产生你提到的错误。另外,请注意 ADL 是在 第二阶段 中完成的。但要做到这一点,我们必须首先成功解析函数 func
.[source 的通用定义:C++ 模板:完整指南:第 250 页倒数第二段]
请注意,允许编译器将错误延迟到实例化,这就是为什么某些编译器可以毫无错误地编译您的代码的原因。 Demo.
案例二
这里我们考虑语句g(p);
.
template<typename T> void func(T p) {
g(p); // NO ERROR
}
int main()
{
}
在这种情况下,名称 g
也是一个 不合格的从属名称 。因此,根据我的回答开头引用的陈述,使用普通查找规则 查找 名称 g
。但是由于此时没有 g
visible 我们有一个错误。这里有两点需要注意:
- 因为这次你没有明确地(通过使用尖括号)调用
g
,所以没有 语法错误。 - 并且由于在这种情况下没有语法错误,并且在您的程序中没有 POI for
func
,所以这里没有错误可以延迟,并且程序编译正常。但是,如果您实例化func
那么您将在实例化时收到错误提示g
was not declared.
模板使用 Two-phase name lookup.
First, at the point of the template definition, the template is checked for syntax.
所以 g(p);
是正确的(从语法的角度来看)(假设函数 g
被 ADL 找到)。
对于 g<T>(p);
,我们有(直到 C++20):
Although a function call can be resolved through ADL even if ordinary lookup finds nothing, a function call to a function template with explicitly-specified template arguments requires that there is a declaration of the template found by ordinary lookup (otherwise, it is a syntax error to encounter an unknown name followed by a less-than character)
g<T>(p);
不正确,(仅解析为 (g < T) > p;
(T
是一种类型,因此是错误的))。
如果存在任何模板函数 g
,则 g
可能被视为模板,并且从语法的角度来看代码是正确的(即使模板参数不匹配)。