c++ - 如何让旧版本的 clang 对 atomic 的默认异常规范感到满意
问题描述
我有一个类,它有一个将 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 和更早的版本对这个结构感到满意?
顺便说一句,这个问题与以下内容有关: gcc接受的带有“noexcept”构造函数的程序,被clang拒绝
虽然该问题讨论了 clang 或 gcc 对于错误或缺少错误是否正确,但我并不关心编译器在理论上做什么是正确的。在以后的版本中,clang 和 gcc 似乎都同意这在形成时是可以的。这很好,但对于需要支持旧编译器的项目没有帮助。我的问题是问我可以做些什么来让旧的编译器满意。
解决方案
作为一种解决方法,您可以创建TimePoint
一个子类(使用noexcept
默认构造函数)而不是 typedef。
#include <atomic>
#include <chrono>
struct A {
A() {}
using Clock = std::chrono::system_clock;
class TimePoint : public Clock::time_point {
public:
using time_point::time_point;
constexpr TimePoint() noexcept : time_point() {}
};
std::atomic<TimePoint> last_allowed_time_;
};
-std=c++1y
对于所有 GCC ≥4.8.1 和 clang ≥3.4.1,这会在 Godbolt 上编译(使用)。
编辑:另外,请注意,以下划线开头的标识符保留用于实现。我喜欢使用尾随下划线(即last_allowed_time_
not _last_allowed_time
)。
推荐阅读
- c# - 多个线程同时写入多个文件 - 它正被另一个进程使用
- haskell - 关于应用程序的多个参数不起作用?
- java - 如何查询按计数分组的对象列表(按最后一天的提及频率)
- c# - 使用 ILGenerator 从 try 和 catch 内部返回一个值
- java - 在匿名类中表示柯里化的方式(从 lambda 表达式转换)。嵌套函数
- python - 为什么 pyauto gui 和 Pycharm 不适合我?
- unit-testing - 在测试 http 请求时使用 Golang context.WithValue
- c++ - 毕达哥拉斯三重嵌套循环的误解
- mongodb-query - 位置数据上的 MongoDB 聚合:如果没有移动,则跳过文档/行
- javascript - JavaScript 条件下的奇怪行为