简体   繁体   English

未优化的 g++ 4.9 上静态 constexpr 的未定义引用

[英]undefined reference for static constexpr on g++ 4.9 with no optimisation

I have the following code:我有以下代码:

#include<chrono>
#include<iostream>

using namespace std::chrono_literals;

#define MSG "hello"
#define DUR 1000ms

class mwe{
    public: 
    static constexpr auto msg = MSG;
    static constexpr auto dur_1 = DUR;
    static constexpr std::chrono::milliseconds dur_2 = DUR;
    static const std::chrono::milliseconds dur_3;
    static constexpr decltype(DUR) dur_4 = DUR;
};

constexpr std::chrono::milliseconds mwe::dur_2; 
const std::chrono::milliseconds mwe::dur_3 = DUR; 
constexpr decltype(DUR) mwe::dur_4;

int main(void) {
    std::cout << "str: " << mwe::msg << std::endl;
    std::cout << "dur_1: " << mwe::dur_1.count() << std::endl;
    std::cout << "dur_2: " << mwe::dur_2.count() << std::endl;
    std::cout << "dur_3: " << mwe::dur_3.count() << std::endl;
    std::cout << "dur_4: " << mwe::dur_4.count() << std::endl;
}

If I compile it (g++ 4.9), via如果我编译它(g++ 4.9),通过

g++ -std=c++14 -O2 test.cpp

everything works like expected, but if I compile it via一切都按预期工作,但如果我通过编译

g++ -std=c++14 -O0 test.cpp

I get the following Error:我收到以下错误:

undefined reference to `mwe::dur_1'

I personally like the way, dur_1 is defined and declared most, but it doesn't work with g++ in my version, if no optimisations are enabled.我个人喜欢这种方式,dur_1 被定义和声明得最多,但如果没有启用优化,它在我的版本中不适用于 g++。 Because all other ways I know (dur_2, dur_3, dur_4) have their drawbacks (redundancy of the value, no auto type deduction, if I would for example change 1000ms to 1s, aso.)因为我知道的所有其他方式(dur_2、dur_3、dur_4)都有其缺点(值的冗余,没有自动类型推导,例如,如果我将 1000 毫秒更改为 1 秒,也一样。)

Do you know, if this is a gcc bug, that the compilation works on production mode, but doesn't work without optimisation?你知道吗,如果这是一个 gcc 错误,编译在生产模式下工作,但没有优化就无法工作?

And is there anoter possible way of getting this working, without defining the location for dur_x outside of the class?是否有另一种可能的方法来让这个工作,而无需在课程之外定义 dur_x 的位置?

It is not a bug in your compiler.这不是编译器中的错误。

You odr-used dur1 but never defined it.odr 使用了dur1但从未定义过它。 And, neither the constexpr nor the inline initialiser make that declaration a definition.而且, constexpr和内联初始化程序都不会将该声明作为定义。

[C++11, C++14: 9.4.2/3]: If a non-volatile const static data member is of integral or enumeration type, its declaration in the class definition can specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression (5.19). [C++11, C++14: 9.4.2/3]:如果非 volatile const static数据成员是整型或枚举类型,则其在类定义中的声明可以指定一个大括号或等号初始值设定项其中每个作为赋值表达式的初始化子句都是一个常量表达式(5.19)。 A static data member of literal type can be declared in the class definition with the constexpr specifier;可以在类定义中使用constexpr说明符声明文字类型的static数据成员; if so, its declaration shall specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression.如果是这样,它的声明应指定一个大括号或等号初始化器,其中每个作为赋值表达式的初始化器子句都是一个常量表达式。 [ Note: In both these cases, the member may appear in constant expressions. [ 注意:在这两种情况下,成员都可能出现在常量表达式中。 —end note ] The member shall still be defined in a namespace scope if it is odr-used (3.2) in the program and the namespace scope definition shall not contain an initializer. —尾注 ]如果在程序中使用 odr (3.2) 并且命名空间范围定义不应包含初始化程序,则该成员仍应在命名空间范围中定义。

As always, optimisation levels may affect the extent to which the compiler is able and/or willing to report such mistakes.与往常一样,优化级别可能会影响编译器能够和/或愿意报告此类错误的程度。

You may write the following to define your member:您可以编写以下内容来定义您的成员:

#include<chrono>

using namespace std::chrono_literals;

#define DUR 1000ms

struct T
{
   static constexpr auto dur_1 = DUR;
};

constexpr decltype(T::dur_1) T::dur_1;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM