类类型的静态constexpr字段在g++中给出链接时间错误

Class-typed static constexpr field giving link-time errors in g++

本文关键字:链接 错误 时间 g++ 类型 静态 constexpr 字段      更新时间:2023-10-16

我今天测试了以下代码片段:

#include <iostream>
struct Literal {
constexpr operator int() const { return 0; }
};
struct Class {
constexpr static const Literal field0 = Literal();
};
int main(void) {
std::cout << "Class::field0: " << Class::field0 << std::endl;
return 0;
}

它编译时没有错误(G++6.2.1),但不幸的是,我在生成可执行文件时遇到了一个链接错误:

/tmp/ccao6eTy.o: In function `main':
test-constexpr-static-field.cpp:(.text+0xa): undefined reference to `Class::field0'
collect2: error: ld returned 1 exit status
[Finished in 0.3s with exit code 1]

阅读本页,我看到了这样的解释:

如果LiteralType的静态数据成员被声明为constexpr,它必须使用初始化器进行初始化,其中每个表达式是一个常量表达式,就在类定义内(…)。

然后我找到了什么是LiteralType的定义,我看到了:

文字类型是以下任意一种:

  • 可能是具有以下所有属性的cv限定类类型:
    • 有一个平凡的析构函数
    • 聚合类型
    • 具有至少一个constexpr(可能是模板)构造函数的类型,该构造函数不是复制或移动构造函数
    • 一个闭包类型(从C++17开始)
  • 所有非静态数据成员和基类都是非易失性文本类型

是否存在Literal不符合LiteralType的情况?在我看来,它有一个琐碎的构造函数,甚至没有内部状态来避免聚合类型或文本类型上的非静态字段的任何麻烦问题。

但考虑到它确实符合(主要是因为程序编译没有错误),为什么会出现链接时间错误?这可能是一个G++错误吗?

显然,我需要在类外添加一个定义

工作示例:

#include <iostream>
struct Literal {
constexpr Literal() = default;
constexpr operator int() const { return 0; }
};
struct Class {
constexpr static const Literal field0 = Literal();
};
// This is needed to avoid undefined reference errors
// This is a definition. Very strange.
constexpr const Literal Class::field0;
int main(void) {
std::cout << "Class::field0: " << Class::field0 << std::endl;
return 0;
}

来源:https://stackoverflow.com/a/8016853/3962396