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

por*_*uod 3 c++ gcc compilation g++

如果std::abs(angle)存在,则以下代码不编译.angle在这种情况下的类型是a 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);
}
Run Code Online (Sandbox Code Playgroud)

仔细查看消息可以验证angle实际上是一个消息short int.但是,如果我正确读取错误,GCC会将其变为a 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>>’
Run Code Online (Sandbox Code Playgroud)

这里发生了什么?即便return (angle<<1) - ((angle*(std::abs<int>(angle)))>>B);如此.

我使用的是gcc 4.6.1版.唯一包含的外部标头是<cmath><cstdint>.编译标志是-std=c++0x -Wall.

fef*_*efe 11

abs()不是模板,而是一组重载函数.根据该标准,对超载int,long,float,double,long 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); }
Run Code Online (Sandbox Code Playgroud)

此模板将采用除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;
}
Run Code Online (Sandbox Code Playgroud)

将它显式地转换为int(std::abs((int)i);)应该可以解决这个问题.


che*_*007 5

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