2012-10-16 50 views
7

这里是我的C++代码(我使用Visual C++ 2010):我该如何避免编译错误:std :: transform?

int absd(int t) 
{ 
    return abs(t); 
} 
int main() 
{ 
    try 
    { 
     int dpi = 137; 
     int dpiCriterionAry[] = {100, 150, 200, 300, 400, 500, 600}; 
     std::vector<int> vec(dpiCriterionAry, dpiCriterionAry + _countof(dpiCriterionAry)); 
     std::transform(vec.begin(), vec.end(), vec.begin(), std::bind1st(std::minus<int>(), dpi)); 
     std::transform(vec.begin(), vec.end(), vec.begin(), absd); 
     //std::transform(vec.begin(), vec.end(), vec.begin(), abs); 
     copy(vec.begin(), vec.end(), ostream_iterator<int>(cout, "\t")); 
     cout << endl; 
    } 
    catch(exception& e) 
    { 
     cerr << e.what() << endl; 
    } 
    return 0; 
} 

当我取消对该行:

//std::transform(vec.begin(), vec.end(), vec.begin(), abs); 

我得到的错误信息:

1>------ Build started: Project: Console, Configuration: Release Win32 ------ 
1>Build started 2012/10/16 21:17:19. 1>InitializeBuildStatus: 1> Creating "..\Intermediate\Console.unsuccessfulbuild" because "AlwaysCreate" was specified. 1>ClCompile: 1> Console.cpp 
1>Console.cpp(16): error C2780: '_OutIt std::transform(_InIt1,_InIt1,_InIt2,_OutIt,_Fn2)' : expects 5 arguments - 4 provided 
1>   D:\ProgramFiles\VS 2010\VC\include\algorithm(1155) : see declaration of 'std::transform' 
1>Console.cpp(16): error C2914: 'std::transform' : cannot deduce template argument as function argument is ambiguous 
1>Console.cpp(16): error C2914: 'std::transform' : cannot deduce template argument as function argument is ambiguous 
1>Console.cpp(16): error C2784: '_OutIt std::transform(_InIt,_InIt,_OutIt,_Fn1)' : could not deduce template argument for '_OutIt' from 'std::_Vector_iterator<_Myvec>' 
1>   with 
1>   [ 
1>    _Myvec=std::_Vector_val<int,std::allocator<int>> 
1>   ] 
1>   D:\ProgramFiles\VS 2010\VC\include\algorithm(1051) : see declaration of 'std::transform' 
1> 
1>Build FAILED. 
1> 
1>Time Elapsed 00:00:02.48 ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ========== 

但是,该行代码:

std::transform(vec.begin(), vec.end(), vec.begin(), absd); 

可以工作。事实上,我使用的是相同的功能:abs,我对结果感到困惑。 此外,我想知道,如果有可能的代码如下两行合并为一个(即一个std::transform调用,具有相同效果):

std::transform(vec.begin(), vec.end(), vec.begin(), std::bind1st(std::minus<int>(), dpi)); 
std::transform(vec.begin(), vec.end(), vec.begin(), absd); 

任何人都可以帮我一下这两个问题?

+7

重载函数在泛型上下文中作为函数指针使用时效果不佳。自从您使用VS2010以来最简单的解决方案:使用lambda。 'std :: transform(vec.begin(),vec.end(),vec。begin(),[&](int i){return abs(dpi-i); });' – Xeo

回答

7

问题是std::absseveral overloads。这就是为什么编译器无法计算出您在std::transform函数调用中尝试使用哪个超载的原因。

为了解决这个问题,你可以做什么@Xeo在他的评论中提到:

std::transform(vec.begin(), vec.end(), vec.begin(), [&](int i){ return abs(i); }); 

或者你可以静投来获得相应的函数地址:

std::transform(vec.begin(), vec.end(), vec.begin(), static_cast<int(*)(int)>(abs)); 

关于你的最后一个问题,是的,lambda作为一种魅力在这里:

std::transform(vec.begin(), vec.end(), vec.begin(), [&](int i) { return absd(dpi - i); }); 
+0

你很棒,你能告诉我第二个问题的解决方案:我想知道是否有可能将以下两行代码合并成一个(这是一个std :: transform调用,具有相同的效果): std :: transform(vec.begin(),vec.end(),vec.begin(),std :: bind1st(std :: minus (),dpi)); std :: transform(vec.begin(),vec.end(),vec.begin(),absd); – Triumphant

+0

@Triumphant当然,你去了。 – mfontanini

2

abs是一个过载而不是一个实体,所以对std::transform的调用不能推导出模板参数,因为没有名称为abs的参考函数。

这是相同的:

void foo(int) { } 
void foo(const char*) { } 

template<typename T> 
int bar(T) 
{ return 0; } 

int i = bar(foo); // which 'foo' ? 

你可以告诉你的话是明确转换成你的意思是函数的类型是指其abs编译:

std::transform(vec.begin(), vec.end(), vec.begin(), (int (*)(int))abs); 

,或者通过创建可变参照你想要的功能:

int (*p)(int) = abs; 
std::transform(vec.begin(), vec.end(), vec.begin(), p); 

To co如Xeo所示,将这两种转换合并为一种可以使用lambda的转换,或者使用例如std::bind

using std::placeholders::_1; 
int (*p)(int) = abs; 
std::transform(vec.begin(), vec.end(), vec.begin(), 
       std::bind(p, std::bind(std::minus<int>(), dpi, _1))); 

或者对于C++ 03,您可以改为使用boost::bind

+0

精彩的回答。第二个问题如何:我想知道是否有可能将以下两行代码合并为一个(即具有相同效果的一个std :: transform调用): std :: transform(vec.begin( ),vec.end(),vec.begin(),std :: bind1st(std :: minus (),dpi)); std :: transform(vec.begin(),vec.end(),vec.begin(),absd); – Triumphant

+0

正如我所说,看Xeo的评论,或者我编辑了答案,以显示如何使用'bind' –

+0

嗨,我得到编译错误: 使用std :: placeholders :: _ 1; int(* p)(int)= abs; std :: transform(vec.begin(),vec.end(),vec.begin(), std :: bind(p,std :: bind(std :: minus (),dpi,_1)) ); D:\ ProgramFiles \ VS 2010 \ VC \ include \ xxcallfun(7):错误C2664:'int(int)':无法将参数1从'std :: tr1 :: _ Bind_fty <_Fty ,_Ret,_BindN>'到'int' – Triumphant