Phiên bản dựa trên mẫu cho phép trình biên dịch nội tuyến cuộc gọi, bởi vì địa chỉ của hàm được biết tại thời gian biên dịch. Rõ ràng, bất lợi là địa chỉ của hàm có để được biết tại thời gian biên dịch (vì bạn đang sử dụng nó làm đối số mẫu) và đôi khi điều này có thể không thực hiện được.Điều đó đưa chúng ta đến trường hợp thứ hai, nơi mà con trỏ hàm chỉ có thể được xác định trong thời gian chạy, do đó làm cho trình biên dịch không thể thực hiện nội tuyến, nhưng cho bạn sự linh hoạt trong việc xác định thời gian chạy hàm được gọi là:
bool runtimeBooleanExpr = /* ... */;
doParam(0, runtimeBooleanExpr ? add1 : add2);
Thông báo, tuy nhiên, có một cách thứ ba:
template<typename F>
void doParam(int i, F f){
std::cout << "Do Param: " << f(i) << "\n";
}
nào giúp bạn linh hoạt hơn và vẫn có lợi thế là biết tại thời gian biên dịch những gì chức năng sẽ được gọi là:
doParam(0, add1);
doParam(0, add2);
Và nó cũng cho phép đi qua bất kỳ đối tượng callable thay vì một con trỏ hàm:
doParam(0, my_functor());
int fortyTwo = 42;
doParam(0, [=] (int i) { return i + fortyTwo; /* or whatever... */ }
Để hoàn chỉnh, đó cũng là một thứ tư cách, sử dụng std::function
:
void doParam(int x, std::function<int(int)> f);
Trong đó có cùng một mức độ tổng quát (trong đó bạn có thể vượt qua bất kỳ đối tượng có thể gọi), nhưng cũng cho phép y để xác định đối tượng có thể gọi tại thời gian chạy - rất có thể với một hình phạt hiệu suất, vì (một lần nữa) nội tuyến trở thành không thể cho trình biên dịch.
Để thảo luận thêm về hai tùy chọn cuối cùng, hãy xem this Q&A on StackOverflow.
Hãy thử 'doParam (0, some_condition? Add1: add2)' để xem sự khác biệt. –