Чому це не працює
Я очікую, що компілятор вирішить 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
, вільна функція чи функція члена.