2012-10-16 47 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