以下显式模板实例化导致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/

10-12 20:32