безопасное целочисленное преобразование в c ++ - PullRequest
1 голос
/ 24 июня 2010

Я хочу создать простую проверку целочисленного диапазона и конвертер с использованием шаблонов c ++.
Код выглядит так:

// D is the "destination" type and S the "source" type
template <class D, class S>
inline D SafeConvert( S value );

template <class S>
inline int SafeConvert<int>( S value ) {

    ASSERT( value >= S(INT_MIN) && value <= S(INT_MAX) );
    return int(value);
} /// error C2768: 'SafeConvert' : illegal use of explicit template arguments


template <class S>
inline size_t SafeConvert<size_t>( S value ) {

    ASSERT( value >= S(0) && value <= S(size_t(-1)) );
    return size_t(value);
} /// error C2768: 'SafeConvert' : illegal use of explicit template arguments


// ...

void test() {

    size_t v = INT_MAX+1;
    int iv = SafeConvert<int>(v);
}

Однако у меня есть следующие ошибки компиляции:

error C2768: 'SafeConvert' : illegal use of explicit template arguments

У меня вопрос, как сказать компилятору, что я хочу специализировать только класс D?

Спасибо.

Ответы [ 4 ]

5 голосов
/ 24 июня 2010

Вы не можете частично специализировать шаблоны функций. Вы должны имитировать это с помощью обертки классов или использовать стандартную перегрузку функций. Пример подражания:

template <typename T1, typename T2>
struct processor;

template < typename T1, typename T2 >
T1 fun(T2 t2) { return processor<T1,T2>::apply(t2); }

template < typename T2 >
struct processor<int,T2>
{
   static int apply(T2 t2) { .... }
};

...etc...
4 голосов
/ 24 июня 2010

Это будет беспокойство и ад, чтобы поддерживать.

Обычно я бы посоветовал использовать numeric_limits:

template <class D, class S>
D SafeConvert(S value)
{
  ASSERT(value >= std::numeric_limits<D>::min()
      && value <= std::numeric_limits<D>::max());
  return static_cast<D>(value);
}

Однако компилятор выдает предупреждение, когда вы сравниваете целое число со знаком с беззнаковым ... (кстати, никогда не понимал этого)

Таким образом, вместо того, чтобы заново изобретать колесо, я посоветую использовать Boost.NumericConversion , а именно: boost::numeric_cast<>.

Гарантируется отсутствие производительности, когда проверка не требуется (т. Е. Тип назначения больше, чем тип источника), а в противном случае выполняйте необходимые проверки.

1 голос
/ 24 июня 2010

Напишите структуру SafeConverter<T, S>, которая используется SafeConvert.Лучше, чем частичная специализация, будет использовать std::numeric_limits или даже boost::numeric_cast, который уже реализует проверку диапазона более сложным способом.

Последняя может быть реализована следующим образом:

template<typename T, typename S>
struct numeric_converter {
  static T convert(const S& val);
}
template<typename T, typename S>
T numeric_cast(const S& val) {
  typedef numeric_converter<T, S> converter;
  return converter::convert(val);
}
0 голосов
/ 24 июня 2010

Просто напишите SafeConvert<size_t, S> вместо SafeConvert<size_t>, я думаю, чтобы специализировать только второй параметр. Ной Робертс также прав в части частичной специализации функций по сравнению с типами.

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