G ++ abs () на коротком int, кажется, превращает его в double? - PullRequest
3 голосов
/ 22 ноября 2011

Следующий код не компилируется, если присутствует std::abs(angle). Тип angle в этом случае short int.

template <class T>
typename T::storage_t::single_t FastSin(const typename T::storage_t::double_t &angle) {
  const int B = (sizeof(typename T::storage_t::single_t)*8) - 2;
  return (angle<<1) - ((angle*(std::abs(angle)))>>B);
}

При внимательном рассмотрении сообщений можно убедиться, что angle на самом деле short int. Однако, если я правильно читаю ошибку, GCC превращает ее в double.

math.hpp: In function ‘typename T::storage_t::single_t FastSin(const typename T::storage_t::double_t&) [with T = Fixed<_t<signed char, short int> >, typename T::storage_t::single_t = signed char, typename T::storage_t::double_t = short int]’:
vector.hpp:106:30:   instantiated from ‘void Vector2<T>::FastRotate(const single_t&) [with T = Fixed<_t<signed char, short int> >, Vector2<T>::single_t = signed char]’
test.cpp:9:18:   instantiated from here
math.hpp:11:52: error: invalid operands of types ‘__gnu_cxx::__enable_if<true, double>::__type {aka double}’ and ‘const int’ to binary ‘operator>>’

Что здесь происходит? Даже return (angle<<1) - ((angle*(std::abs<int>(angle)))>>B); делает то же самое.

Я использую gcc версии 4.6.1. Включены только внешние заголовки <cmath> и <cstdint>. Флаги компиляции: -std=c++0x -Wall.

Ответы [ 3 ]

11 голосов
/ 22 ноября 2011

abs() - это не шаблон, а набор функций перегрузки. Согласно стандарту, перегрузка для int, long, float, double, long double должна существовать. Но перегрузки для short не существует. Но поскольку последовательность преобразования из short в int является только повышением, а форма последовательности преобразования short в другие перегруженные типы является преобразованием, следует выбрать перегрузку для int.

Но в g ++ (для меня версия 4.5.2) в cmath добавлен нестандартный шаблон:

template<typename _Tp>
inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value,
    double>::__type
abs(_Tp __x)
{ return __builtin_fabs(__x); }

Этот шаблон будет принимать все встроенные целочисленные типы, кроме int и long, и будет возвращать значение double.

На самом деле, использование типа unsigned int также приводит к этой ошибке в g ++:

#include <cstdlib>
#include <cmath>
int main() {
    unsigned int i,j;
    i=0;
    j=std::abs(i)>>2;
    return 0;
}

Явное приведение к int (std::abs((int)i);) должно решить эту проблему.

4 голосов
/ 22 ноября 2011

Функция std::abs() не является шаблоном в C ++;Есть только несколько перегрузок для разных типов.Единицы для целочисленных типов находятся в заголовке <cstdlib>.См. http://www.cplusplus.com/reference/clibrary/cstdlib/abs/ и http://www.cplusplus.com/reference/clibrary/cmath/abs/ для получения дополнительной информации.

0 голосов
/ 05 февраля 2014

Я знаю, что на этот пост уже давно дан ответ, но я просто хочу дать другую точку зрения, которая должна помочь кому-то еще.Моя проблема была с QT и mingw, всегда, когда я собирал с boost или некоторыми другими библиотеками, использующими cmath и cstdlib, я получал эту ошибку.Через некоторое время я был очень раздражен этой ошибкой и решил немного изучить эти два файла.Я полностью согласен с fefe и его ответом, но это может решить проблемы, только если вы используете это в своей программе или библиотеке, и вы с самого начала знаете, в чем проблема, и это не было моей проблемой.

Есливам действительно нужно включить оба файла одновременно (вам нужны system, malloc ... и все математические функции) быстрое и грязное решение - открыть заголовок и на 106 строке (на моем компьютере) вы увидите что-то вроде этого:

    namespace std _GLIBCXX_VISIBILITY(default)
    {
    _GLIBCXX_BEGIN_NAMESPACE_VERSION

      using ::div_t;
      using ::ldiv_t;

      using ::abort;
      //using ::abs;
      using ::atexit;
      using ::atof;
      using ::atoi;
      using ::atol;
      using ::bsearch;
      using ::calloc;
.
.
.

Из приведенного выше кода вы можете видеть, что cstdlib имеет функцию abs в пространстве имен std, и вам необходимо закомментировать эту строку, чтобы разрешить использование функции cmath abs и избавиться от этой неприятной ошибки.

Я надеюсь, что это кому-то поможет, и я прошу прощения за такой длинный пост.

...