So sánh std::function và std::invoke
Trong C++, cả std::function và std::invoke đều dùng để làm việc với các đối tượng callable (hàm, lambda, functor, con trỏ hàm), nhưng chúng phục vụ hai mục đích khác nhau:
std::function: Lưu trữ callable để gọi sau.std::invoke: Gọi callable ngay tại thời điểm sử dụng.
1. Signature là gì?
Trong C++, signature của hàm (định danh hàm) bao gồm:
- Kiểu trả về (Return Type): Kiểu dữ liệu mà hàm trả về.
- Kiểu tham số (Parameter Types): Kiểu dữ liệu của từng tham số hàm nhận vào.
Ví dụ:
int add(int a, int b) {
return a + b;
}
Signature của hàm add() là:
- Kiểu trả về:
int - Kiểu tham số:
(int, int)
2. std::function - Lưu trữ callable
std::function là một template class cho phép lưu trữ và gọi các callable có cùng signature.
Cách hoạt động:
- Khi tạo std::function, ta phải xác định signature của callable.
- Sau đó, callable nào khớp với signature đó có thể được gán vào.
- Để gọi callable, ta dùng
operator().
Ví dụ:
#include <iostream>
#include <functional>
int add(int a, int b) { return a + b; }
auto multiply = [](int a, int b) { return a * b; };
int main() {
std::function<int(int, int)> operation;
operation = add;
std::cout << "Kết quả cộng: " << operation(5, 3) << std::endl;
operation = multiply;
std::cout << "Kết quả nhân: " << operation(5, 3) << std::endl;
return 0;
}
Khi nào nên dùng std::function?
- ✅ Khi cần lưu trữ callable để gọi sau.
- ✅ Khi muốn truyền callable vào hàm mà không dùng template.
- ✅ Khi cần thay đổi callable linh hoạt.
3. std::invoke - Gọi callable ngay lập tức
std::invoke là một template hàm giúp gọi callable một cách tổng quát.
Cách hoạt động:
- Truyền vào callable và các tham số.
std::invoketự động gọi callable đó.
Ví dụ:
#include <iostream>
#include <functional>
int subtract(int a, int b) { return a - b; }
struct Divider {
double operator()(double a, double b) const { return a / b; }
};
int main() {
Divider divide;
std::cout << "Kết quả trừ: " << std::invoke(subtract, 10, 4) << std::endl;
std::cout << "Kết quả chia: " << std::invoke(divide, 10.0, 2.0) << std::endl;
return 0;
}
Khi nào nên dùng std::invoke?
- ✅ Khi muốn gọi callable ngay lập tức.
- ✅ Khi viết code tổng quát (generic programming) mà không biết callable là kiểu gì.
- ✅ Khi gọi hàm thành viên của class một cách tự động.
All rights reserved