Mengapa tidak berhasil
Saya mengharapkan kompiler untuk menyelesaikan f()
dengan tipe iterator. Rupanya, itu (gcc 4.1.2) tidak melakukannya.
Akan lebih bagus jika itu masalahnya! Namun, for_each
adalah template fungsi, dideklarasikan sebagai:
template <class InputIterator, class UnaryFunction>
UnaryFunction for_each(InputIterator, InputIterator, UnaryFunction );
Pemotongan template perlu memilih jenis untuk UnaryFunction
pada saat panggilan. Tetapi f
tidak memiliki tipe tertentu - ini adalah fungsi yang kelebihan beban, ada banyak f
yang masing-masing memiliki tipe yang berbeda. Saat ini tidak ada cara untuk for_each
membantu proses pemotongan template dengan menyatakan yang f
diinginkan, jadi pemotongan template gagal. Agar pemotongan template berhasil, Anda perlu melakukan lebih banyak pekerjaan di situs panggilan.
Solusi umum untuk memperbaikinya
Melompat ke sini beberapa tahun dan C ++ 14 kemudian. Daripada menggunakan a static_cast
(yang akan memungkinkan pemotongan template berhasil dengan "memperbaiki" yang f
ingin kita gunakan, tetapi mengharuskan Anda untuk melakukan resolusi berlebih secara manual untuk "memperbaiki" yang benar), kami ingin membuat kompilator berfungsi untuk kita. Kami ingin f
mengajukan beberapa argumen. Dengan cara yang paling umum, itu:
[&](auto&&... args) -> decltype(auto) { return f(std::forward<decltype(args)>(args)...); }
Itu banyak untuk diketik, tapi masalah semacam ini sering muncul menjengkelkan, jadi kita bisa membungkusnya dalam makro (menghela napas):
#define AS_LAMBDA(func) [&](auto&&... args) -> decltype(func(std::forward<decltype(args)>(args)...)) { return func(std::forward<decltype(args)>(args)...); }
dan kemudian gunakan saja:
void scan(const std::string& s) {
std::for_each(s.begin(), s.end(), AS_LAMBDA(f));
}
Ini akan melakukan apa yang Anda inginkan dari kompilator - melakukan resolusi overload pada namanya f
dan melakukan hal yang benar. Ini akan berfungsi terlepas dari apakah f
fungsi bebas atau fungsi anggota.