如果存在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
。
答案 0 :(得分:11)
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);
)可以解决此问题。
答案 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函数并摆脱那个讨厌的错误。
我希望这会对某人有所帮助,我很抱歉这么长的帖子。