代码之家  ›  专栏  ›  技术社区  ›  mljli

emplace_back导致静态constexr成员上的链接错误

  •  12
  • mljli  · 技术社区  · 7 年前

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

    如果我切换到C++ 17,它就编译得很好。我发现,在C++ 17中,静态COSTEXPR数据成员是隐式的。 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;
    }
    
    1 回复  |  直到 7 年前
        1
  •  9
  •   songyuanyao    7 年前

    如你所说, emplace_back 引用参数,因此传递 base_trait::n 使它成为 odr-used .

    如果一个对象的值是读(除非它是编译时常量)或写的,它的地址是取的,或者它的引用是绑定到它的,那么就使用ODR;

    基特征::n 这里是必需的。但是由于C++ 17的行为改变了,因为 constexpr static data member 不再需要类外定义。

    如果一个警察 non-inline (since C++17) 静态数据成员 or a constexpr static data member (since C++11) 如果使用了ODR,则仍需要命名空间范围中的定义,但它不能具有初始值设定项。 This definition is deprecated for constexpr data members (since C++17).

    静态数据成员可以内联声明。可以在类定义中定义内联静态数据成员,并且可以指定初始值设定项。它不需要类外定义。(因为C++ 17)