Почему не работает
Я ожидаю, что компилятор будет разрешен f()
по типу итератора. По-видимому, он (gcc 4.1.2) этого не делает.
Было бы здорово, если бы это было так! Тем не менее, for_each
это шаблон функции, объявленный как:
template <class InputIterator, class UnaryFunction>
UnaryFunction for_each(InputIterator, InputIterator, UnaryFunction );
Шаблон вычета должен выбрать тип для UnaryFunction
в точке вызова. Но f
не имеет определенного типа - это перегруженная функция, есть много f
s с разными типами. В настоящее время нет способа for_each
помочь процессу вывода шаблонов, указав, чего f
он хочет, поэтому вывод шаблонов просто не удался. Для успешного вывода шаблона вам нужно проделать дополнительную работу на сайте вызовов.
Общее решение для его устранения
Прыгнул сюда через несколько лет, а C ++ 14 позже. Вместо того, чтобы использовать static_cast
(который позволил бы вывести шаблон успешно, путем «исправления», который f
мы хотим использовать, но требует, чтобы вы вручную сделали разрешение перегрузки, чтобы «исправить» правильное), мы хотим заставить компилятор работать на нас. Мы хотим f
привести некоторые аргументы. В наиболее общем виде это:
[&](auto&&... args) -> decltype(auto) { return f(std::forward<decltype(args)>(args)...); }
Это много, чтобы напечатать, но такого рода проблемы возникают раздражающе часто, поэтому мы можем просто обернуть это в макрос (вздох):
#define AS_LAMBDA(func) [&](auto&&... args) -> decltype(func(std::forward<decltype(args)>(args)...)) { return func(std::forward<decltype(args)>(args)...); }
а затем просто используйте его:
void scan(const std::string& s) {
std::for_each(s.begin(), s.end(), AS_LAMBDA(f));
}
Это будет делать именно то, что вы хотели, чтобы компилятор делал - выполнял разрешение перегрузки для самого имени f
и просто делал правильные вещи. Это будет работать независимо от того, f
является ли свободная функция или функция-член.