2010-04-30 91 views
4

如果我不重載myfunc,它可以工作。C++ STL 101:過載函數會導致編譯錯誤

void myfunc(int i) 
{ 
    std::cout << "calling myfunc with arg " << i << std::endl; 
} 
void myfunc(std::string s) 
{ 
    std::cout << "calling myfunc with arg " << s << std::endl; 
} 
void testalgos() 
{ 
    std::vector<int> v; 
    v.push_back(1); 
    v.push_back(2); 

    std::vector<std::string> s; 
    s.push_back("one"); 
    s.push_back("two"); 

    std::for_each(v.begin(), v.end(), myfunc); 
    std::for_each(s.begin(), s.end(), myfunc); 
    return; 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    std::cout << "Hello World" << std::endl; 
    testalgos(); 
    return 0; 
} 

以下構建錯誤會針對for_each調用重複進行。

錯誤C2914: '的std :: for_each的':不能推導出模板參數的函數的參數不明確 錯誤C2784: '_Fn1的std :: for_each的(_Init,_init,_Fn1)':不能推導出模板參數'_InIt'from'std :: _ Vector_iterator < _Ty,_Alloc>'。

如果我不重載myfunc,它可以工作。有人解釋這裏發生了什麼。

TIA

+0

看起來像你有你的代碼標籤倒退。你能解決嗎? – 2010-04-30 16:09:43

+0

編譯器告訴你這個說法是不明確的。你是否期望編譯器爲你選擇其中之一?好的問題是「我怎樣才能消除這個電話的歧義?」。 – 2010-04-30 17:29:33

回答

10

在這種情況下,編譯器無法解決重載問題。 std::for_each()期望某些任意類型的F作爲它的仿函數,而不是某種特定的函數類型,因此這裏重載的myFunc不明確。

可以明確選擇哪些超載使用:

std::for_each(v.begin(), v.end(), (void (*)(int))myfunc); 
std::for_each(s.begin(), s.end(), (void (*)(std::string))myfunc); 

替代(最後兩個是從評論)

typedef void (*IntFunc)(int); 
std::for_each(/*...*/, (IntFunc)myfunc); 

typedef void IntFunc(int); 
std::for_each(/*...*/, static_cast<IntFunc*>(&myFunc)); 

// using identity (e.g. from boost or C++0x): 
std::for_each(/*...*/, (identity<void(int)>::type*)myfunc); 
+0

謝謝。所以,編譯器確實無法解決,我們需要添加「提示」。只是好奇,我需要在所有的STL或模板相關的代碼? – Sidjal 2010-04-30 16:28:23

+0

這取決於您調用的模板函數 - 如果可以解決過載問題,則不需要它。 'template void f(T,void(*)(T))''可以在'f(someInt,myFunc)'下正常工作。 STL主要使用完全不受限制的類型作爲函數參數,但需要*「提示」*。 – 2010-04-30 16:39:31

+1

typedef也可以在沒有parens的情況下工作,顯式編寫'*'和C++風格類型轉換:'typedef void IntFunc(int); std :: for_each(...,static_cast (&myFunc));' – Potatoswatter 2010-04-30 18:26:24

4

編譯器不能推斷仿函數的類型。你可以讓你的函數模板:

template<typename T> void myfunc(T); 

template<> void myfunc(int i) 
{ 
    std::cout << "calling myfunc with arg " << i << std::endl; 
} 
template<> void myfunc(std::string s) 
{ 
    std::cout << "calling myfunc with arg " << s << std::endl; 
} 

然後按如下方式使用它:

std::for_each(v.begin(), v.end(), myfunc<int>); 
std::for_each(s.begin(), s.end(), myfunc<std::string>); 
+0

我想我正在尋找這樣的事情。謝謝。回到我的教程。 – Sidjal 2010-04-30 16:56:50

+2

如果不需要模板,大多數人都希望純重載。有關注意事項,請參閱http://www.gotw.ca/publications/mill17.htm。 – Potatoswatter 2010-04-30 18:38:09

2

編譯器無法推斷出使用,因爲這兩個重載將匹配參數(不依賴於以任何方式迭代器的類型)同樣好。

除了顯式將參數顯式轉換爲合適的指針類型之外,另一種選擇可能是使用std::ptr_fun幫助器函數將其包含在函子中,並通過顯式地給出(部分)幫助模板推演。

std::for_each(v.begin(), v.end(), std::ptr_fun<int>(myfunc)); 
std::for_each(s.begin(), s.end(), std::ptr_fun<std::string>(myfunc)); 
相關問題