Dlaczego to nie działa
Spodziewałbym się, że kompilator rozwiąże f()
typ iteratora. Najwyraźniej to (gcc 4.1.2) tego nie robi.
Byłoby wspaniale, gdyby tak było! Jednak for_each
jest to szablon funkcji zadeklarowany jako:
template <class InputIterator, class UnaryFunction>
UnaryFunction for_each(InputIterator, InputIterator, UnaryFunction );
Odliczenie szablonowe należy wybrać typ UnaryFunction
w momencie połączenia. Ale f
nie ma określonego typu - jest to przeciążona funkcja, istnieje wiele f
typów, z których każdy ma inny typ. Obecnie nie ma sposobu, for_each
aby wspomóc proces odliczania według szablonu, określając, czego f
chce, więc odliczenie szablonowe po prostu się nie udaje. Aby odliczenie szablonu zakończyło się sukcesem, musisz wykonać więcej pracy w witrynie wezwania.
Ogólne rozwiązanie tego problemu
Wskoczę tutaj kilka lat i C ++ 14 później. Zamiast używać a static_cast
(co pozwoliłoby na pomyślną dedukcję szablonu przez „naprawienie”, którego f
chcemy użyć, ale wymaga ręcznego rozwiązania problemu z przeciążeniem, aby „naprawić” poprawne), chcemy, aby kompilator działał za nas. Chcemy wywołać f
kilka argumentów. W najbardziej ogólny sposób jest to:
[&](auto&&... args) -> decltype(auto) { return f(std::forward<decltype(args)>(args)...); }
To dużo do pisania, ale tego rodzaju problem pojawia się irytująco często, więc możemy po prostu zawrzeć to w makro (westchnienie):
#define AS_LAMBDA(func) [&](auto&&... args) -> decltype(func(std::forward<decltype(args)>(args)...)) { return func(std::forward<decltype(args)>(args)...); }
a potem po prostu go użyj:
void scan(const std::string& s) {
std::for_each(s.begin(), s.end(), AS_LAMBDA(f));
}
Zrobi to dokładnie to, co chcesz, aby zrobił kompilator - wykona rozwiązanie przeciążenia na f
samej nazwie i po prostu zrób to, co trzeba. Będzie to działać niezależnie od tego, czy f
jest to funkcja wolna, czy funkcja składowa.