Использование boost :: numeric_cast <> - PullRequest
14 голосов
/ 13 декабря 2010

Когда я хочу преобразовать различные целочисленные типы, кажется, что лучший синтаксис - использовать boost::numeric_cast<>():

int y = 99999;
short x = boost::numeric_cast<short>(y); // will throw an exception if y is too large

Я никогда не использовал это; однако синтаксис довольно прост, так что все хорошо.

Теперь предположим, что я хочу сделать что-то более продвинутое: вместо того, чтобы генерировать исключение, я бы хотел, чтобы он возвращал минимум или максимум целевого типа (насыщенность). Я не мог найти способ выразить это, но документация предполагает, что это возможно (возможно, с использованием политики RawConverter). Все, что я мог придумать, это следующее уродливое:

short x = numeric_cast<short>(max(min(y, SHORT_MAX), SHORT_MIN);

Так, как я могу выразить "насыщающий бросок", используя буст numeric_cast?

Ответы [ 2 ]

15 голосов
/ 13 декабря 2010

Возможно, вы могли бы сделать что-то вроде этого:

#include <limits>

template<typename Target, typename Source>
Target saturation_cast(Source src) {
   try {
      return boost::numeric_cast<Target>(src);
   }
   catch (const boost::negative_overflow &e) {
      return std::numeric_limits<Target>::lowest();
      /* Or, before C++11:
      if (std::numeric_limits<Target>::is_integer)
         return std::numeric_limits<Target>::min();
      else
         return -std::numeric_limits<Target>::max();
      */
   }
   catch (const boost::positive_overflow &e) {
      return std::numeric_limits<Target>::max();
   }
}

(для типов, которые поддерживают его, ошибки также могут возвращать -inf / + inf).

Таким образом, вы разрешаете Boostnumeric_cast определяет, находится ли значение за пределами и может ли реагировать соответствующим образом.

2 голосов
/ 13 декабря 2010

Хм ... Если все вышеперечисленное сработает, общее решение, вероятно, было бы сделать что-то вроде:

template<typename TypeFrom, typename TypeTo>
TypeTo saturated_cast(TypeFrom value) {
    TypeTo valueMin = std::numeric_limits<TypeTo>::min();
    TypeTo valueMax = std::numeric_limits<TypeTo>::max();
    return boost::numeric_cast<TypeTo>( std::max(std::min(value,valueMax),valueMin) );
}

Надеюсь, я понял правильно ... В любом случае, у вас есть концепция :)

.... Кстати: я думаю, что вместо этого вы могли бы использовать static_cast, потому что после выполнения ограничения вы больше не можете переполнять диапазон, поэтому вам не требуется дополнительная проверка numeric_cast.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...