gpt4 book ai didi

c++ - 在 C++ 模板实例化中查找依赖名称

转载 作者:IT老高 更新时间:2023-10-28 21:57:37 24 4
gpt4 key购买 nike

当我尝试编译这段代码时

// void foobar(int); 

template <class T>
struct Foo {
void bar(T t) { foobar(t); };
};

void foobar(int);

template class Foo<int>;

使用 g++ 4.8.2 我收到以下错误消息

foo.cc: In instantiation of ‘void Foo<T>::bar(T) [with T = int]’:
foo.cc:10:16: required from here
foo.cc:5:27: error: ‘foobar’ was not declared in this scope, and no
declarations were found by argument-dependent lookup at
the point of instantiation [-fpermissive]
void bar(T t) { foobar(t); };
^
foo.cc:8:6: note: ‘void foobar(int)’ declared here, later in the translation unit
void foobar(int);
^

(使用 clang 3.4 几乎相同)。

首先,我认为代码是正确的并且应该编译,因为 foobar 是模板声明中的一个依赖名称,并且应该只在模板实例化的第二阶段查找。当这在最后一行完成时,'foobar(int)' 已经被声明了。顺便说一句,当我取消最上面一行的注释时,代码会编译,但两个声明都在实例化之前,所以这无关紧要。

其次,错误信息本身对我来说似乎是矛盾的。它说“在实例化时没有找到声明”,即 foo.cc:10:16,它说它是在 foo.cc:8:6 处“稍后”声明的。根据我对数字和英语的了解,我将其称为“之前”而不是“之后”。

那么,这是 gcc 中的错误还是我做错了什么?由于这在我看来是一种常见的使用模式,但我不太相信。

顺便说一句:当我在 MSDN (http://msdn.microsoft.com/en-us/library/dx2zs2ee.aspx) 上使用 g++ 尝试“依赖类型的名称解析”的第二个示例时,结果与 vc++ 不同,后者(通常不是,但在这种特定情况下)会破坏这一点是 g++ 中的一个错误。

最佳答案

tl;博士 Foo<int>不调用任何 ADL,但 Foo<X>会(其中 X 是类类型)。


首先,在这段代码中foobar是一个从属名称,因为 (C++14/N3936) [temp.dep]/1

In an expression of the form:

postfix-expression ( expression-list opt )

where the postfix-expression is an unqualified-id, the unqualified-id denotes a dependent name if [...]

  • any of the expressions in the expression-list is a type-dependent expression (14.6.2.2), or

t是从属名称,因为它是声明 T t 的一部分在哪里 T是一个模板参数,因此是一个依赖类型。

转到依赖名称解析,有 [temp.dep.res]/1它引入了这样一个事实,即可以在定义上下文和实例化上下文中查找名称,并定义实例化上下文的位置。为简洁起见,我省略了它,但在此示例中为 template class Foo<int>;是实例化的点。

下一位是[temp.dep.candidate]/1 :

For a function call where the postfix-expression is a dependent name, the candidate functions are found using the usual lookup rules (3.4.1, 3.4.2) except that:

  • For the part of the lookup using unqualified name lookup (3.4.1), only function declarations from the template definition context are found.
  • For the part of the lookup using associated namespaces (3.4.2), only function declarations found in either the template definition context or the template instantiation context are found.

最后两部分是两阶段查找的“两个阶段”。 (注意——本节的措辞从 C++11 更改为 C++14,但效果相同)。

在第一阶段 3.4.1 中,找不到 foobar 的名称.


所以我们进入第二阶段。查找名称的实际地点如 3.4.2 中所述。文字很长,但这里有两条相关规则:

  • If T is a fundamental type, its associated sets of namespaces and classes are both empty.

  • If T is a class type (including unions), its associated classes are: the class itself; the class of which it is a member, if any; and its direct and indirect base classes. Its associated namespaces are the innermost enclosing namespaces of its associated classes. [...]

所以当你实例化 Foo<int> ,则查找的第二阶段不会引入任何额外的命名空间进行搜索。

但是,如果您将示例更改为 struct X {};然后更改intX到处,然后代码确实编译。这是因为后一个要点:类类型参数的 ADL 会搜索该类的封闭命名空间(现在是全局命名空间),但是内置类型参数的 ADL 不会搜索全局命名空间。

关于c++ - 在 C++ 模板实例化中查找依赖名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27178483/

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