Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ STL 101: Overload function causes build error

Tags:

c++

stl

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 as 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

like image 375
Sidjal Avatar asked Dec 06 '22 02:12

Sidjal


2 Answers

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);
like image 73
Georg Fritzsche Avatar answered Dec 14 '22 23:12

Georg Fritzsche


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>);
like image 35
Kirill V. Lyadvinsky Avatar answered Dec 14 '22 22:12

Kirill V. Lyadvinsky