Tại sao nó không hoạt động
Tôi mong muốn trình biên dịch giải quyết f()
theo kiểu lặp. Rõ ràng, nó (gcc 4.1.2) không làm điều đó.
Sẽ thật tuyệt nếu đó là trường hợp! Tuy nhiên, for_each
là một mẫu hàm, được khai báo là:
template <class InputIterator, class UnaryFunction>
UnaryFunction for_each(InputIterator, InputIterator, UnaryFunction );
Khấu trừ mẫu cần chọn một loại cho UnaryFunction
điểm tại của cuộc gọi. Nhưng f
không có một loại cụ thể - đó là một hàm quá tải, có nhiều f
loại với mỗi loại khác nhau. Không có cách nào hiện tại for_each
để hỗ trợ quá trình khấu trừ mẫu bằng cách nêu rõ f
nó muốn, vì vậy việc khấu trừ mẫu đơn giản là thất bại. Để việc khấu trừ mẫu thành công, bạn cần thực hiện nhiều công việc hơn trên trang web cuộc gọi.
Giải pháp chung để sửa nó
Nhảy vào đây một vài năm và C ++ 14 sau đó. Thay vì sử dụng static_cast
(sẽ cho phép khấu trừ mẫu thành công bằng cách "sửa" mà f
chúng tôi muốn sử dụng, nhưng yêu cầu bạn phải tự giải quyết quá tải để "sửa" chính xác), chúng tôi muốn làm cho trình biên dịch hoạt động cho chúng tôi. Chúng tôi muốn gọi f
về một số đối số. Theo cách chung nhất có thể, đó là:
[&](auto&&... args) -> decltype(auto) { return f(std::forward<decltype(args)>(args)...); }
Đó là rất nhiều loại, nhưng loại vấn đề này xuất hiện thường xuyên một cách khó chịu, vì vậy chúng ta chỉ có thể gói nó trong một macro (thở dài):
#define AS_LAMBDA(func) [&](auto&&... args) -> decltype(func(std::forward<decltype(args)>(args)...)) { return func(std::forward<decltype(args)>(args)...); }
và sau đó chỉ cần sử dụng nó:
void scan(const std::string& s) {
std::for_each(s.begin(), s.end(), AS_LAMBDA(f));
}
Điều này sẽ làm chính xác những gì bạn muốn trình biên dịch đã làm - thực hiện giải quyết quá tải trên f
chính tên đó và chỉ cần làm đúng. Điều này sẽ hoạt động bất kể f
là chức năng miễn phí hay chức năng thành viên.