gpt4 book ai didi

c++ - 在定义模板后声明函数

转载 作者:太空狗 更新时间:2023-10-29 20:02:27 25 4
gpt4 key购买 nike

假设我有一个模板函数:

template <class T>
void tfoo( T t )
{
foo( t );
}

稍后我想将它与类型一起使用,所以我声明/定义一个函数并尝试调用它:

void foo( int );

int main()
{
tfoo(1);
}

我从 g++ 得到错误:

‘foo’ was not declared in this scope, and no declarations were found by argument-dependent lookup at the point of instantiation [-fpermissive] foo( t );

为什么在实例化时找不到void foo(int)?它是在那个时候宣布的。有没有办法让它工作(无需在模板之前移动 foo 的声明)?

最佳答案

foo在您的例子中是一个从属名称,因为如果参数和参数类型取决于模板参数,则函数选择取决于类型。这意味着 foo按照依赖查找的规则进行查找。

依赖非依赖 查找之间的区别在于,在依赖查找的情况下,ADL 指定的 namespace 被视为 extended:它们扩展了从模板实例化的角度可见的额外名称(在您的情况下为 tfoo 调用)。这包括出现在模板声明之后的名称。这里的关键点是只有 ADL 指定的命名空间以这种方式扩展。

(通过 ADL 命名空间,我指的是函数参数类型相关联的命名空间,因此被相关名称查找规则考虑在内。参见“3.4.2参数相关的名称查找")

在您的例子中,参数的类型为 int . int是一个基本类型。基本类型没有关联的命名空间(参见“3.4.2 Argument-dependent name lookup”),这意味着它不通过 ADL 命名任何命名空间。在您的示例中,根本不涉及 ADL。 foo 的相关名称查找在这种情况下与非依赖查找没有什么不同。它将无法看到您的 foo ,因为它是在模板下方声明的。

注意与下面例子的区别

template <class T> void tfoo( T t )
{
foo( t );
}

struct S {};

void foo(S s) {}

int main()
{
S s;
tfoo(s);
}

此代码将编译自参数类型 S是一个类类型。它有一个关联的命名空间——全局命名空间——它添加(指定)该全局命名空间以进行相关名称查找。此类 ADL 指定的 namespace 可通过依赖查找以其更新 形式看到(从调用点看)。这就是为什么查找可以看到foo并成功完成。


当人们认为所谓的“双阶段查找”的第二阶段应该能够看到下面额外声明的一切时,这是一个相当普遍的误解模板定义一直到实例化点(在本例中为调用点)。

不,第二阶段并没有看到一切。它可以仅在与函数参数关联的命名空间中看到额外的东西。所有其他 namespace 都不会更新。它们看起来就像是从模板定义的角度观察到的。

关于c++ - 在定义模板后声明函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40875453/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com