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により、"safe-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; }
};

残念ながら、展開された寸法/単位ライブラリはこれを行っていないようです。std::chrono::duration(この質問は、aが負かどうかを実際にテストしたかったために発生しました)。これは役に立ちますか?失敗するケースはありますか?ゼロとの比較を許可する簡単な方法はありますか?

個々の演算子に対してこれを実装する代わりに、リテラルゼロからユニットタグ付き型への暗黙的な変換が存在するはずであると思われます。


私はそれが許可することに注意します

 X{1} < nullptr

有効な式として:(、残念ながら、アクセスできないタイプのオーバーロードを提供しても、std::nullptr_tこれは修正されません。これは、標準がセクション4.10で述べているためです

整数型の null ポインター定数は、型の prvalue に変換できますstd::nullptr_t

4

2 に答える 2

3
  1. はい。あなたは、これが有用であることを私に簡単に納得させました。
  2. については、すでに障害点を指摘していnullptrます。それ以外に思いつきませんでした。許可しないがすべて
    を許可するメカニズムを考案しようとした私の試みは、機能しない複雑なスキームを生み出しました。基本的に、C++ に関数パラメーターが必要であることを伝える方法がないため、引数を取る関数を考案するのは困難です (まだ不可能とは言いません...)。ありません。nullptr0constexprint0
  3. を許可しても問題ない場合は、別のクラスではなく直接nullptr使用する方が簡単に実装できます。(確かに、実装で型にアクセスする方法がないため、それほど安全ではありません。)std::nullptr_tsafe_zero_idiomsafe_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 に答える