简体   繁体   English

std :: abs与std :: transform不起作用

[英]std::abs with std::transform not working

Take this example: 举个例子:

#include <vector>
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cmath>

void PrintVec(const std::vector<float>&);
int main(int argc, char * argv[]){

float vals[] = {-1.2,0.0,1.2};
std::vector<float> test(vals, vals + sizeof(vals) / sizeof(float));
std::vector<float> absTest(3);

std::transform(test.begin(), test.end(), absTest.begin(), std::abs<float>());

PrintVec(test);
PrintVec(absTest);

return 0;
}

void PrintVec(const std::vector<float> &vec){
for (unsigned int i = 0; i < vec.size(); ++i){
    std::cout << vec[i] << '\n';
}
return;
}

Using both gcc 4.3.4 and VS 2013 I get compiler errors. 同时使用gcc 4.3.4和VS 2013会出现编译器错误。 For gcc its: 对于gcc:

testTransformAbs.cpp:15: error: expected primary-expression before 'float' testTransformAbs.cpp:15:错误:“浮动”之前的预期主表达式

For VS 2013 its: 对于VS 2013,其:

error C2062: type 'float' unexpected 错误C2062:意外键入“浮动”

If I remove <float> then I get this error: 如果删除<float>则会出现此错误:

testTransformAbs.cpp:15: error: no matching function for call to 'abs()' /usr/include/stdlib.h:766: note: candidates are: int abs(int) /usr/include/c++/4.3/cstdlib:144: note: long int std::abs(long int) /usr/include/c++/4.3/cstdlib:175: note: long long int __gnu_cxx::abs(long long int) /usr/include/c++/4.3/cmath:99: note: double std::abs(double) /usr/include/c++/4.3/cmath:103: note: float std::abs(float) /usr/include/c++/4.3/cmath:107: note: long double std::abs(long double) testTransformAbs.cpp:15:错误:没有匹配的函数可调用'abs()'/usr/include/stdlib.h:766:注意:候选对象是:int abs(int)/usr/include/c++/4.3/cstdlib :144:注意:long int std :: abs(long int)/usr/include/c++/4.3/cstdlib:175:注意:long long int __gnu_cxx :: abs(long long int)/usr/include/c++/4.3 / cmath:99:注意:double std :: abs(double)/usr/include/c++/4.3/cmath:103:注意:float std :: abs(float)/usr/include/c++/4.3/cmath:107 :注意:long double std :: abs(long double)

I can create my own function 我可以创建自己的功能

float MyAbs(float f){
    return sqrt(f * f);
}

std::transform(test.begin(), test.end(), absTest.begin(), MyAbs);

And everything works. 一切正常。 The reference on cplusplus.com says that the fourth input can be an UnaryOperation defined by: cplusplus.com上的参考资料说,第四个输入可以是一个UnaryOperation,其定义如下:

Unary function that accepts one element of the type pointed to by InputIterator as argument, and returns some result value convertible to the type pointed to by OutputIterator. 一元函数,将InputIterator指向的类型的一个元素作为参数,并返回一些可转换为OutputIterator指向的类型的结果值。 This can either be a function pointer or a function object. 这可以是一个函数指针或一个函数对象。

To me this should be able to use std::abs() . 对我来说,这应该可以使用std::abs() I also tried fabs with the same result. 我也尝试过fabs ,结果也一样。 What am I missing? 我想念什么?

std::abs is an overloaded function, not a template function. std::abs是一个重载函数,而不是模板函数。 When obtaining a pointer to the function, you can choose a specific overload by casting: 获取指向函数的指针时,可以通过强制转换来选择特定的重载:

std::transform(test.begin(), test.end(), absTest.begin(),
    static_cast<float (*)(float)>(&std::abs));

or by using a function pointer variable: 或通过使用函数指针变量:

float (*fabs)(float) = &std::abs;
std::transform(test.begin(), test.end(), absTest.begin(), fabs);

Note that I also removed the () you put after abs , since this is a function and not a class that needs to be instantiated. 请注意,我还删除了abs后面的() ,因为这是一个函数,而不是需要实例化的类。

std::abs is not a template . std::abs不是模板 Any function in headers prefixed with ac like cmath or cstdlib do not have any C++ features like templates, because they represent the C standard library. 标头中以ac cmath标头中的任何函数(如cmathcstdlib都没有任何C ++功能(如模板),因为它们表示C标准库。 Also std::abs is for integral types. std::abs也适用于整数类型。 You should be using std::fabs for floating point types. 您应该将std :: fabs用于浮点类型。

I dont like function pointer casts, so in cases like this one, i usually write some wrappers like these: 我不喜欢函数指针强制转换,所以在这种情况下,我通常会写一些如下的包装器:

namespace hlp {
template <class T> struct iabs { 
    static_assert(std::is_integral<T>::value, "");
    T operator()(T const& t){ return std::abs(t); } 
};
template <class T> struct fabs { 
    static_assert(std::is_floating_point<T>::value, ""); 
    T operator()(T const& t){ return std::fabs(t); } 
};
}

You can use those wrappers like you wanted to use std::abs in your question. 您可以像在问题中使用std :: abs一样使用这些包装器。 The static_assert will generate a clean compiler error when you try to use the integral version for floating point types or vice versa. 当您尝试将整数版本用于浮点类型时, static_assert会生成干净的编译器错误,反之亦然。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM