处理单位安全代码中的字面零

Ben*_*igt 10 c++ unit-conversion

除了极少数例外(看着你,华氏温度和摄氏温度标度),单位是线性的,零值同时是所有单位的附加标识.

所以给定

auto speed = dimensioned(20, _meter/_second);
auto power = dimensioned(75, _watt);
Run Code Online (Sandbox Code Playgroud)

然后

if (speed < 6) ...
if (power > 17) ...
Run Code Online (Sandbox Code Playgroud)

没有比这更有意义了

if (speed > power) ...
Run Code Online (Sandbox Code Playgroud)

你应该写

if (speed < dimensioned(6, _mile/_hour)) ...
Run Code Online (Sandbox Code Playgroud)

但是,这有意义:

if (speed < 0)
Run Code Online (Sandbox Code Playgroud)

因为0 m/s == 0 mph == 0 AU /两周或你想要使用的任何其他单位(速度).那么问题是如何启用此功能并仅启用此用法.

C++ 11显式运算符和上下文转换bool摆脱了"安全布尔"成语的需要.看来这个问题可以通过类似的"安全零"成语来解决:

struct X
{
  int a;
  friend bool operator<(const X& left, const X& right) { return left.a < right.a; }
private:
  struct safe_zero_idiom;
public:
  friend bool operator<(const X& left, safe_zero_idiom*) { return left.a < 0; }
};
Run Code Online (Sandbox Code Playgroud)

不幸的是,部署的维度/单元库似乎没有这样做.(这个问题的出现是因为我实际上想测试一个是否std::chrono::duration为负).这有用吗?是否有导致其失败的案例?有没有更简单的方法来允许比较为零?

人们怀疑,不是为个体运营商实现这一点,而是应该存在从字面零到单元标记类型的隐式转换.


我注意到它允许

 X{1} < nullptr
Run Code Online (Sandbox Code Playgroud)

作为一个有效的表达式:(,不幸的是,提供类型的无法访问的重载std::nullptr_t并不能解决这个问题,因为标准在第4.10节中说明了

可以将整数类型的空指针常量转换为类型的prvalue std::nullptr_t.

jxh*_*jxh 3

  1. 是的。你很容易就让我相信这很有用。
  2. 您已经指出了一个失败点,对于nullptr. 除此之外我想不出别的什么了。
    我尝试设计一种机制来禁止nullptr但允许0所有产生的复杂方案,但行不通。基本上,由于没有办法告诉 C++ 你想要一个constexpr函数参数,所以很难(我不会说不可能......)设计一个带有int参数的函数,但如果参数值会导致编译时失败不是0
  3. 如果您同意允许nullptr,那么更简单的实现是std::nullptr_t直接使用而不是单独的safe_zero_idiom类。(不可否认,它并不安全,因为无法访问safe_zero_idiom实现中的类型。)

struct X
{
  int a;
  friend bool operator<(const X& left, const X& right) { return left.a < right.a; }
  friend bool operator<(const X& left, std::nullptr_t) { return left.a < 0; }
};
Run Code Online (Sandbox Code Playgroud)