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