一个短的int上的G ++ abs()似乎把它变成了一个双重?

时间:2011-11-22 12:20:01

标签: c++ gcc compilation g++

如果存在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 个答案:

答案 0 :(得分:11)

abs()不是模板,而是一组重载函数。根据该标准,intlongfloatdoublelong double的重载应该存在。但short的重载不存在。但是,由于从shortint的转换序列只是促销,而转化序列从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); }

此模板将采用intlong以外的所有内置整数类型,并返回double的值。

事实上,使用类型unsigned int也会在g ++中产生此错误:

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

明确地将其强制转换为intstd::abs((int)i);)可以解决此问题。

答案 1 :(得分:4)

std::abs()函数不是C ++中的模板;为不同类型提供了几个重载。整数类型的标题位于标题<cstdlib>中。有关详细信息,请参阅http://www.cplusplus.com/reference/clibrary/cstdlib/abs/http://www.cplusplus.com/reference/clibrary/cmath/abs/

答案 2 :(得分:0)

我知道这篇文章很久以前就已经回答了,但我只想提出另一个应该帮助别人的观点。我的问题是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在std命名空间中有函数abs,你需要注释该行以便能够使用cmath abs函数并摆脱那个讨厌的错误。

我希望这会对某人有所帮助,我很抱歉这么长的帖子。