以下显式模板实例化导致clang++ 11.0
上的LLVM x86_64-pc-windows-msvc
下使用clang-cl
接口(interface)和-std=c++17
进行编译器前端segfault,而与优化级别无关。A.h
template <typename T>
class A
{
public:
T value;
static constexpr auto address = &A<T>::value;
};
extern template class A<float>;
A.cpp
#include "A.h"
template class A<float>;
请注意,由于C++ 17 A::address
是一个内联变量,因此在这里使用ODR不会成为问题。编译器的行为显然是错误的,我已经在LLVM Bug Tracker上提交了一份报告。
尽管如此,我仍然对代码的实际正确性感到好奇。
是由编译器错误处理的未定义行为,还是代码本身没有任何问题,仅与编译器有关。就个人而言,我在显式模板实例化规范的标准中找不到任何东西,这表明上述代码是错误的。
我不认为以上内容格式错误,是否缺少某些内容?
最佳答案
您的示例类A
用过的如下例所示(完整demo here)
#include <iostream>
#include "A.h"
int main() {
A<float> af{42.F}; // uses explicit instantiation: no implicit instantiation occurs.
A<int> ai{43}; // implicit instantiation.
std::cout << af.*A<float>::address // 42
<< "\n" << ai.*A<int>::address; // 43
}
格式正确,很自然是编译器崩溃导致的(ICE;内部编译器错误)编译器错误。除非您自己的程序还包含不恰当放置的显式特化(请参阅下文),或者与上面的最小示例有很大不同,否则您自己的程序也应格式正确。细节
[temp.explicit]/14需要一个显式的实例化声明[强调我的]:
这些要求都满足了上面的示例,对
A
的定义要求也要满足,按照[temp.explicit]/5对其特化的显式定义。最后,[temp.spec]/5包含[强调我的]的其他要求:
(5.1)已实现,因为
A<float>
的显式实例化定义位于单个转换单元内(常见的格式不正确的NDR错误是不小心将显式实例化定义放置在 header 中,其中 header 包含在多个源文件中) 。 (5.2)不适用,因为不存在A
的显式特化(针对任何特化),并且(5.3)随后不适用,因为不存在会与后者的显式实例化定义相冲突的A<float>
专门化的显式特化。最后请注意,按照[temp.local]/2的规定,您可以在初始化类模板
A
的静态数据成员address
时使用注入(inject)的类名称A
:template <typename T>
class A {
public:
T value;
static constexpr auto address = &A::value;
};
关于c++ - 在clang 11上显式模板实例化期间的编译器segfault,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/65613231/