За очень немногими исключениями (глядя на вас, шкалы температуры Фаренгейта и Цельсия) единицы являются линейными, а значение нуля одновременно является аддитивным тождеством для всех единиц сразу.
Итак, данный
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 м/с == 0 миль/ч == 0 A.U./fortnight или любые другие единицы, которые вы хотите использовать (для скорости). Тогда возникает вопрос, как включить это и только это использование.
С++ 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; }
};
- Демо: http://ideone.com/vUxmxi
К сожалению, похоже, что развернутые библиотеки размерности/единицы не делают этого. (Этот вопрос возник, потому что я действительно хотел проверить, был ли std::chrono::duration
отрицательным). Это полезно? Есть ли случаи, которые могут привести к его провалу? Есть ли более простой способ разрешить сравнение с нулем?
Предполагается, что вместо того, чтобы внедрять это для отдельных операторов, должно существовать неявное преобразование из буквенного нуля в теги, помеченные тегом.
Я отмечаю, что он позволяет
X{1} < nullptr
как допустимое выражение:( и, к сожалению, предоставление недоступной перегрузки типа std::nullptr_t
не исправляет это, поскольку стандарт говорит в разделе 4.10
Константа нулевого указателя интегрального типа может быть преобразована в prvalue типа
std::nullptr_t
.