gpt4 book ai didi

c++ - 类模板的名称是否在限定的外部析构函数定义的范围内?

转载 作者:行者123 更新时间:2023-12-04 11:59:51 26 4
gpt4 key购买 nike

使用 clang-11 编译时,最新版本的 clang(自 -pedantic 起)发出警告对于以下代码段:

namespace foo {
template <int A>
struct Bar {
~Bar();
};
} // namespace foo

template <int A>
foo::Bar<A>::~Bar(){}
生成的警告(以及 -Werror 的错误)是:
<source>:10:12: error: ISO C++ requires the name after '::~' to be found in the same scope as the name before '::~' [-Werror,-Wdtor-name]
foo::Bar<A>::~Bar(){}
~~~~~~~~~~~^~
::Bar
Live Example clang是我见过的第一个发出此诊断的编译器,据我所知,上面写的内容是完全有效的 C++。似乎抑制这种情况的两种不同方式是 define within the same namespaceexplicitly qualify the destructor name - 如:
...
template <int A>
foo::Bar<A>::~Bar<A>(){}
Clang 在这里的诊断是否正确? 我的理解是类型的名称绝对在正确的名称范围内,如 foo::Bar<A>::~ -- 以及 ~Bar<A>()的资质应该是不必要的。

最佳答案

从发布问题后我了解到,严格来说,这个警告是正确的——尽管它很可能是标准措辞的缺陷。
根据理查德·史密斯在 LLVM Bug 46979 中的说法:

The diagnostic is correct, per the standard rules as written; strictly-speaking, the C++ rules require this destructor to be written as

template<typename T>
A::B<T>::~B<T>()

Per C++ [basic.lookup.qual]p6:

In a qualified-id of the form:

nested-name-specifier[opt] type-name :: ~ type-name

the second type-name is looked up in the same scope as the first.


这意味着在类 A 中查找第二个 B,它只找到类模板 B 而不是注入(inject)的类名。
这不是一个特别有用的规则,并且可能不是预期的规则,这就是为什么默认情况下禁用此诊断(以及一堆类似的看似合理但形式上不正确的析构函数名称的诊断)但包含在 -pedantic 中的原因。

进一步研究这一点,我可以找到提到的 [basic.lookup.qual]/6 的段落。在 C++20 标准中,但似乎 C++23 的草案已经改变了这一点——这表明这很可能是一个缺陷。
在 C++23 的 [basic.lookup.qual] 草案中,整个部分已经过大修,目前,在撰写本文时,替换为 [basic.lookup.qual]/4其中指出:

If a qualified name Q follows a ~:

(4.1) If Q is a member-qualified name, it undergoes unqualified lookup as well as qualified lookup.

(4.2) Otherwise, its nested-name-specifier N shall nominate a type.If N has another nested-name-specifier S, Q is looked up as if its lookup context were that nominated by S.

(4.3) Otherwise, if the terminal name of N is a member-qualified name M, Q is looked up as if ~Q appeared in place of M (as above).

(4.4) Otherwise, Q undergoes unqualified lookup.

(4.5) Each lookup for Q considers only types (if Q is not followed by a <) and templates whose specializations are types.If it finds nothing or is ambiguous, it is discarded.

(4.6) The type-name that is or contains Q shall refer to its (original) lookup context (ignoring cv-qualification) under the interpretation established by at least one (successful) lookup performed.

[Example 4:

struct C {
typedef int I;
};
typedef int I1, I2;
extern int* p;
extern int* q;
void f() {
p->C::I::~I(); // I is looked up in the scope of C
q->I1::~I2(); // I2 is found by unqualified lookup
}
struct A {
~A();
};
typedef A AB;
int main() {
AB* p;
p->AB::~AB(); // explicitly calls the destructor for A
}

— end example]


(由于这是草稿,因此全文已发布在此处,将来可能会更改措辞)
这似乎通过确保按预期执行查找来明确纠正此问题。
因此,由于措辞中的缺陷,在旧版本的 C++ 下诊断基本上是正确的——但 C++23 似乎改变了这一点。我不确定这是否会在旧版本中作为缺陷被追溯修复,因为似乎没有编译器实际上遵循这个迂腐的要求。

关于c++ - 类模板的名称是否在限定的外部析构函数定义的范围内?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68751682/

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