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::invoke
tự độ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.