假设我有一个模板函数:
template <class T>
void tfoo( T t )
{
foo( t );
}
后来我想将它与类型一起使用,所以我声明/定义一个函数并尝试调用它:
void foo( int );
int main()
{
tfoo(1);
}
我从 g++ 收到错误:
“foo”未在此范围内声明,并且在实例化时通过参数相关查找未找到任何声明 [-fpermissive]
脚 );
为什么它找不到void foo(int)
在实例化点?那时就宣布了。有没有办法让它工作(不移动声明foo
在模板之前)?
foo
你的情况是附属名称,因为如果参数和参数类型取决于模板参数,则函数选择取决于类型。这意味着foo
是按照以下规则查找的依赖查找.
和...之间的不同依赖的 and 非依赖性查找是在依赖查找的情况下ADL 提名的命名空间被视为extended:它们使用从模板实例化点可见的额外名称进行扩展(tfoo
根据您的情况致电)。其中包括出现在模板声明之后的名称。这里的关键点是onlyADL 命名的命名空间就是以这种方式扩展的。
(By ADL 命名的命名空间我指的是命名空间有关联函数参数类型,因此被依赖名称查找规则考虑在内。请参阅“3.4.2 依赖于参数的名称查找”)
在你的情况下,参数有类型int
. int
是一个基本类型。基本类型没有关联的命名空间(请参阅“3.4.2 参数相关名称查找”),这意味着它不通过 ADL 指定任何命名空间。在您的示例中,ADL 根本不涉及。从属名称查找foo
在这种情况下与非依赖查找没有什么不同。它将无法看到您的foo
,因为它已声明below模板。
注意与以下示例的区别
template <class T> void tfoo( T t )
{
foo( t );
}
struct S {};
void foo(S s) {}
int main()
{
S s;
tfoo(s);
}
此代码将因参数类型而编译S
是一个类类型。它有一个关联的命名空间 - 全局命名空间 - 并且它添加(指定)该全局命名空间以进行依赖名称查找。此类 ADL 命名的命名空间可通过其相关查找来查看updated形式(从调用的角度来看)。这就是为什么lookup可以看到foo
并成功完成。
当人们相信第二阶段所谓的“两阶段查找”应该可以看到一切这是在模板定义下面额外声明的,一直到实例化点(在本例中为调用点)。
不,第二阶段并没有看到一切。它可以看到额外的东西仅在与函数参数关联的命名空间中。所有其他命名空间都不会更新。它们看起来就像是从模板定义的角度观察到的。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)