开发者

C++ STL 101: Overload function causes build error

Trivial code that works if I do not overload myfunc.

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;
}

The following build errors repeat for both for_each calls.

error C2914: 'std::for_each' : cannot deduce template argument a开发者_JS百科s function argument is ambiguous error C2784: '_Fn1 std::for_each(_InIt,_InIt,_Fn1)' : could not deduce template argument for '_InIt' from 'std::_Vector_iterator<_Ty,_Alloc>'.

It does work if I do not overload myfunc.Can someone explain what is happening here.

TIA


In that context the overloads can't be resolved by the compiler. std::for_each() expects some arbitrary type F for its functor, not some specific function type, thus the overloaded myFunc is ambiguous here.

You can explicitly select which overload to use:

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

Alternatives (last two are from the comments):

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);


Compiler cannot deduce type of functor. You could make your function template:

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;
}

Then use it as follows:

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


The compiler cannot deduce which to use, as both overloads would match the argument (which doesn't depend on the types of the iterator in any way) equally well.

Another option in addition to explicitly casting the argument to suitable pointer type might be here to use the std::ptr_fun helper function to wrap it in a functor, and help the template deduction by giving (part of) it explicitly.

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));
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜