2010-04-30 96 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)); 
相关问题