c++ - emplace_back 导致静态 constexpr 成员上的链接错误

标签 c++ language-lawyer c++17 constexpr one-definition-rule

为什么emplace_back 引用需要定义的成员? emplace_back(integer literal)emplace_back(static constexpr integer member) 有什么区别?

如果我切换到 C++17,它编译得很好。我发现在 C++17 中静态 constexpr 数据成员是隐式的 inlined .这是否意味着编译器隐式地为它们创建了一个定义?

示例代码:

class base {
    int n;
public:
    base(int n):n(n) {}
};

struct base_trait {
    static constexpr int n = 1;
};

int main(void) {
    vector<base> v;
    v.emplace_back(1);  // ok
    v.emplace_back(base_trait::n);  // link error with -std=c++14, ok with -std=c++17
    return 0;
}

最佳答案

正如你所说,emplace_back 通过引用获取参数,因此传递 base_trait::n 会导致它为 odr-used .

an object is odr-used if its value is read (unless it is a compile time constant) or written, its address is taken, or a reference is bound to it;

在C++17之前,这意味着这里需要base_trait::n的定义。但是从 C++17 开始,行为发生了变化,对于 constexpr static data member不再需要类外定义。

If a const non-inline (since C++17) static data member or a constexpr static data member (since C++11) is odr-used, a definition at namespace scope is still required, but it cannot have an initializer. This definition is deprecated for constexpr data members (since C++17).

A static data member may be declared inline. An inline static data member can be defined in the class definition and may specify an initializer. It does not need an out-of-class definition. (since C++17)

关于c++ - emplace_back 导致静态 constexpr 成员上的链接错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50549359/

相关文章:

c++ - 可以在 make 调用中使用 BUILD_MODE 吗?

c++ - 为什么这个派生类可以用 `{}` 而不是在 C++17 上用 `()` 构造?

c++ - 在 Xcode 中使用 std::variant

c++ - 为什么这段 C++ 代码不起作用?

c++ - 使用指针访问结构体的各个字节

c++ - Qt布局,传递和不传递QWidget作为父级之间的区别

c++ - 不同编译器调用的不同类型转换运算符

c - 有符号整数类型及其对应的无符号整数类型

c++ - 打破一个 TU 内的 ODR?

c++ - C++17 中的新表达式求值顺序