10

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

所以给定

auto speed = dimensioned(20, _meter/_second);
auto power = dimensioned(75, _watt);

然后

if (speed < 6) ...
if (power > 17) ...

没有意义

if (speed > power) ...

你应该写

if (speed < dimensioned(6, _mile/_hour)) ...

但是,这确实有意义:

if (speed < 0)

因为 0 m/s == 0 mph == 0 AU/fortnight 或您愿意使用的任何其他单位(用于速度)。那么问题是如何启用这个并且只有这个用法。

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

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

有人怀疑,不应该为单个运算符实现这一点,而应该存在从字面量零到单元标记类型的隐式转换。


我确实注意到它允许

 X{1} < nullptr

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

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

4

2 回答 2

3
  1. 是的。你很容易让我相信这很有用。
  2. 您已经指出了一个失败点,对于nullptr. 我想不出除此之外的任何事情。
    我试图设计一种机制来禁止nullptr但允许0所有人都产生了不起作用的复杂方案。基本上,因为没有办法告诉 C++ 你想要一个constexpr函数参数,所以很难(我不会说不可能......)设计一个接受int参数的函数,但是如果参数值会导致编译时失败不是0
  3. 如果您同意allowing 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; }
};
于 2013-09-26T03:33:18.573 回答
0

我只能想出一个明显的解决方案,偏离你想要的:

#include <stdexcept>
#include <iostream>
#include <type_traits>
using namespace std;

#include <boost/mpl/int.hpp>

using namespace boost::mpl;

struct X
{
    int a;

    friend bool operator<(const X& left, const X& right)
    {
        return left.a < right.a;
    }

    template< typename T >
    friend bool operator<(const X& left, T zero)
    {
        static_assert( is_same<int_<0>, T>::value, "cannot compare against arbitrary things");
        return left.a < 0;
    }
};

int_<0> unitless0;


int main()
{
    X x;

    //if (x < 3) cout << "oopsie";  // we get a build error here as excpected.

    if (x < unitless0)
        cout << "ok";

    return 0;
}
于 2013-09-26T05:41:42.817 回答