【发布时间】:2021-03-29 22:58:49
【问题描述】:
我有一个类,它有一个将 std time_point 包装在原子中的成员变量。我很难让较旧的编译器对此感到满意。我最初在接受 10 之前的 GCC 版本时遇到了问题。我通过显式初始化解决了这个问题。
我认为这让所有编译器都很高兴。但是,一旦我的代码投入生产,我在使用较旧的 clang 编译器的更彻底的 CI(与 PR CI 相比)中遇到了一个问题。该项目是 Apache Traffic Server,所以它是开源的,如果查看它是有趣的。代码如下:
https://github.com/apache/trafficserver/blob/master/include/tscore/Throttler.h#L117
这是一个演示问题的最小示例:
#include <atomic>
#include <chrono>
struct A {
A() {}
using Clock = std::chrono::system_clock;
using TimePoint = Clock::time_point;
// The explicit initialization is needed by
// GCC earlier than 10.
std::atomic<TimePoint> _last_allowed_time{TimePoint{}};
};
错误可以在godbolt中重现: https://godbolt.org/z/4db4osf66
这是错误:
In file included from <source>:1:
/opt/compiler-explorer/gcc-8.3.0/lib/gcc/x86_64-linux-gnu/8.3.0/../../../../include/c++/8.3.0/atomic:194:7: error: exception specification of explicitly defaulted default constructor does not match the calculated one
atomic() noexcept = default;
^
<source>:12:26: note: in instantiation of template class 'std::atomic<std::chrono::time_point<std::chrono::_V2::system_clock, std::chrono::duration<long, std::ratio<1, 1000000000> > > >' requested here
std::atomic<TimePoint> _last_allowed_time{TimePoint{}};
^
1 error generated.
Compiler returned: 1
使用 Godbolt 配置,任何比 clang 9 更新的东西都不会引发此错误。我想我可以 ifdef 解决它,但我不确定如果我这样做的解决方法是什么。显式初始化让 gcc 很高兴。我该怎么做才能让 clang 8 及更早版本对这种结构感到满意?
顺便说一下,这个问题与以下内容有关: Program with "noexcept" constructor accepted by gcc, rejected by clang
虽然该问题讨论了 clang 或 gcc 对于错误或没有错误是否正确,但我并不关心编译器在理论上做什么是正确的。在以后的版本中,clang 和 gcc 似乎都同意这在形成时是可以的。这很好,但对于需要支持旧编译器的项目没有帮助。我的问题是问我可以做些什么来让旧的编译器满意。
【问题讨论】:
-
std::atomic<TimePoint> _last_allowed_time(TimePoint());seems to work(从 Clang 5.0.0 开始)。 -
A()=default修复了吗? -
@PaulSanders 这行得通。谢谢你。好,易于。如果您将其发布为答案,我会接受。
-
@PaulSanders:实际上,它可以编译,但我认为它做的事情与我们预期的不同。在使用该“变量”时,它现在表示它被解释为“非静态成员函数”。所以我认为该行被解释为一个函数而不是一个成员变量。
-
@MooingDuck:不,这不能解决问题。