std::function
có một chữ ký cố định. Đây là một lựa chọn thiết kế, không phải là một yêu cầu khó khăn. Viết một pseudo std::function
hỗ trợ nhiều chữ ký không phải là khó khăn:
template<class...Sigs>
struct functions;
template<>
struct functions<> {
functions()=default;
functions(functions const&)=default;
functions(functions&&)=default;
functions& operator=(functions const&)=default;
functions& operator=(functions&&)=default;
private:
struct never_t {private:never_t(){};};
public:
void operator()(never_t)const =delete;
template<class F,
std::enable_if_t<!std::is_same<std::decay_t<F>, functions>{}, int>* =nullptr
>
functions(F&&) {}
};
template<class S0, class...Sigs>
struct functions<S0, Sigs...>:
std::function<S0>,
functions<Sigs...>
{
functions()=default;
functions(functions const&)=default;
functions(functions&&)=default;
functions& operator=(functions const&)=default;
functions& operator=(functions&&)=default;
using std::function<S0>::operator();
using functions<Sigs...>::operator();
template<class F,
std::enable_if_t<!std::is_same<std::decay_t<F>, functions>{}, int>* =nullptr
>
functions(F&& f):
std::function<S0>(f),
functions<Sigs...>(std::forward<F>(f))
{}
};
sử dụng:
auto f = [](int a = 3) {std::cout << a << std::endl; };
functions<void(int), void()> fs = f;
fs();
fs(3);
Live example.
Điều này sẽ tạo một bản sao riêng biệt của lambda của bạn cho mỗi quá tải. Nó thậm chí có thể có lambdas khác nhau cho quá tải khác nhau với đúc cẩn thận.
Bạn có thể viết một cái không làm điều này, nhưng về cơ bản nó sẽ yêu cầu thực hiện lại std::function
với trạng thái nội bộ sáng hơn.
Phiên bản nâng cao hơn ở trên sẽ tránh sử dụng thừa kế tuyến tính, vì kết quả là mã O (n^2) và độ sâu mẫu đệ quy O (n) trên số chữ ký. Một thừa kế cây nhị phân cân bằng giảm xuống đến mã O (n lg n) được tạo ra và độ sâu O (lg n).
Phiên bản cường độ công nghiệp sẽ lưu trữ thông tin trong lambda một lần, sử dụng tối ưu hóa đối tượng nhỏ, có hướng dẫn giả vtable sử dụng chiến lược thừa kế nhị phân để gửi cuộc gọi hàm và lưu trữ con trỏ hàm được gửi đến trong giả vtable. Nó sẽ lấy không gian O (# chữ ký) * sizeof (con trỏ hàm) trong cơ sở mỗi lớp (không phải mỗi trường hợp), và sử dụng khoảng phí trên mỗi trường hợp như std::function
.
Nhưng điều đó hơi nhiều đối với bài đăng SO, phải không?
start of it
'auto h = f;'? – MikeCAT
Tôi không nghĩ rằng 'std :: function' có bất kỳ hỗ trợ tham số mặc định nào. – chris
@MikeCAT Tôi biết rằng :) Cách chính xác là gì nếu tôi muốn chỉ định đầy đủ loại, nếu có? –