使用g++ 4.9进行静态constexpr编译时出现未定义引用,且未启用优化。

4

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;
}

如果我通过以下方式编译它(使用g++ 4.9):

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

一切都按预期运行,但如果我通过编译

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

I get the following Error:

undefined reference to `mwe::dur_1'

我个人最喜欢dur_1的定义和声明方式,但如果没有启用优化,它在我的版本中无法与g++配合使用。 因为我所知道的所有其他方法(dur_2、dur_3、dur_4)都有它们的缺点(值冗余、没有自动类型推断,例如如果我将1000ms更改为1s等)。
你知道吗,如果这是gcc的一个bug,在生产模式下编译可以工作,但在没有优化的情况下不起作用吗?
还有没有其他可能的方法可以使其工作,而无需在类外定义dur_x的位置?

dur_1 没有被定义。不确定你的期望是什么。 - Lightness Races in Orbit
1个回答

8
这并不是编译器的错误。
你使用了 `dur1`,但从未定义它。而且,无论是 `constexpr` 还是内联初始化器都不能将该声明视为定义。
引用如下内容:
如果非易失性 const 静态数据成员是整型或枚举类型,则其在类定义中的声明可以指定一个大括号或等于初始化器,在其中每个初始化程序子句都是常量表达式(5.19)。如果静态数据成员是字面类型,则可以在类定义中使用 constexpr 说明符声明它;如果这样做,则其声明应指定一个大括号或等于初始化器,在其中每个初始化程序子句都是常量表达式。[注意:在这两种情况下,该成员可能出现在常量表达式中。-注释]如果在程序中使用了 odr-used (3.2) 并且命名空间范围定义中不包含初始化器,则仍须在命名空间范围内定义该成员。
一如既往,优化级别可能会影响编译器报告此类错误的程度和意愿。
您可以写以下内容来定义您的成员:
#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;

我不明白为什么g++要求在“dur_1”的定义上使用“constexpr”。 - dyp
@dyp:在我看来,他们误读了[dcl.constexpr]/1,这个细节要求所有constexpr声明都符合条件,除了这种情况。 - Lightness Races in Orbit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接