0

So sánh std::function và std::invoke

Trong C++, cả std::functionstd::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.

All rights reserved

Bình luận

Đang tải thêm bình luận...
Avatar
0
Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí