C ++ STL 101: функция перегрузки вызывает ошибку сборки - PullRequest
4 голосов
/ 30 апреля 2010

Тривиальный код, который работает, если я не перегружаю 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;
}

Следующие ошибки сборки повторяются для обоих вызовов for_each.

ошибка C2914: 'std :: for_each': невозможно вывести аргумент шаблона, поскольку аргумент функции неоднозначен ошибка C2784: «_Fn1 std :: for_each (_InIt, _InIt, _Fn1)»: не удалось вывести аргумент шаблона для «_InIt» из «std :: _ Vector_iterator <_Ty, _Alloc>».

Это работает, если я не перегружаю myfunc.Может кто-нибудь объяснить, что здесь происходит.

1012 * ТИА *

Ответы [ 3 ]

10 голосов
/ 30 апреля 2010

В этом контексте перегрузки не могут быть разрешены компилятором. 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);
4 голосов
/ 30 апреля 2010

Компилятор не может определить тип функтора. Вы можете сделать свой шаблон функции:

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>);
2 голосов
/ 30 апреля 2010

Компилятор не может определить, какой из них использовать, поскольку обе перегрузки будут одинаково соответствовать аргументу (который никак не зависит от типов итератора).

Другой вариант, помимо явного приведения аргумента к подходящему типу указателя, может быть здесь - использовать вспомогательную функцию 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));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...