Почему не работает
Я ожидаю, что компилятор разрешит f()
по типу итератора. Видимо, он (gcc 4.1.2) этого не делает.
Было бы здорово, если бы это было так! Однако for_each
является шаблоном функции, объявленным как:
template <class InputIterator, class UnaryFunction>
UnaryFunction for_each(InputIterator, InputIterator, UnaryFunction );
Для вывода шаблона необходимо выбрать тип для UnaryFunction
в точке вызова. Но f
не имеет определенного типа - это перегруженная функция, существует множество f
с разными типами. Для 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
свободной функцией или функцией-членом.