Bạn không thể sử dụng std::function
theo cách đó.
Bạn có thể tự cuộn, nhưng sẽ mất một số công việc.
Đây là một phác thảo:
template<class T, class A, class B>
struct sub{using type=T;};
template<class T, class A, class B>
using sub_t=typename sub<T,A,B>::type;
template<class T, class B>
struct sub<T,T,B>{using type=B;};
template<class R,class...Args,class A,class B>
struct sub<R(Args...),A,B>{
using type=sub_t<R,A,B>(sub_t<Args,A,B>...);
};
viết ở trên. Nó có loại T
và nếu nó khớp với A
, nó trả về B
. Nếu không, nó sẽ trả lại T
. Nó cũng hoạt động trên các chữ ký chức năng.
Chúng ta có thể sử dụng điều này với một 'cờ' gõ vào một chữ ký để thay thế với các loại đối tượng chức năng chính:
struct recurse{}; // flag type
// not needed in C++14:
template<class Sig>
using result_of_t=typename std::result_of<Sig>::type;
template<class Sig>
struct func {
using Sig2=sub_t<Sig,recurse,func>;
using function = std::function<Sig2>;
function impl;
template<class...Ts>
result_of_t<function const&(Ts...)>
operator()(Ts&&...ts)const
{
return impl(std::forward<Ts>(ts)...);
}
};
Sau đó func<recurse()>
là một đối tượng hàm rằng khi gọi, trả về một func<recurse()>
.
Thực hiện việc triển khai đơn giản như lưu trữ std::function<Sig2>
và gọi điện. Đoạn mã trên thiếu đánh bóng - bạn muốn nhà thầu, nhiều nhà khai thác, bảo mật, vv
live example
Lưu ý rằng một y-combinator có thể có ích nếu bạn muốn tránh phải chụp một bản sao của chính mình bằng cách tham chiếu để trả về *this
trong một lambda, khi chụp bằng tham chiếu ngụ ý một thời gian giới hạn (và tránh sử dụng ptr được chia sẻ).
Công việc khác hữu ích sẽ được tăng cường sub
để xử lý tham chiếu đến A
hoặc thậm chí các mẫu chứa A
làm đối số. (thuật toán phụ chung không thể thực hiện được trong C++, vì C++ không có khả năng siêu mẫu đầy đủ, nhưng việc xử lý mọi lớp mẫu hiện tại trong std
rất dễ dàng: chúng đều là các mẫu kiểu thuần túy, hoặc std::array
).
Để hoàn chỉnh, bạn có thể thêm video này vào sub
:
// optional stuff for completeness:
template<class T,class A,class B>
struct sub<T&,A,B>{
using type=sub_t<T,A,B>&;
};
template<class T,class A,class B>
struct sub<T*,A,B>{
using type=sub_t<T,A,B>*;
};
template<template<class...>class Z,class... Ts,class A,class B>
struct sub<Z<Ts...>,A,B>{
using type=Z<sub_t<Ts,A,B>...>;
};
template<template<class,size_t>class Z,class T,size_t n,class A,class B>
struct sub<Z<T,n>,A,B>{
using type=Z<sub_t<T,A,B>,n>;
};
template<class T,size_t n,class A,class B>
struct sub<T[n],A,B>{
using type=sub_t<T,A,B>[n];
};
template<class T,class A,class B>
struct sub<T[],A,B>{
using type=sub_t<T,A,B>[];
};
template<class T,class A,class B>
struct sub<T const,A,B>{
using type=sub_t<T,A,B> const;
};
template<class T,class A,class B>
struct sub<T volatile const,A,B>{
using type=sub_t<T,A,B> volatile const;
};
template<class T,class A,class B>
struct sub<T volatile,A,B>{
using type=sub_t<T,A,B> volatile;
};
Và nó hiện đang làm việc một cách đệ quy trên nhiều mẫu, trên mảng, tài liệu tham khảo, và con trỏ, và với các loại cv-đủ điều kiện. Điều này cho phép bạn viết một cái gì đó như:
func< std::vector<recurse>() >
mà là một đối tượng hàm mà operator()
trả về một func< std::vector<recurse>() >
.
Lưu ý rằng quy trình này không hoàn toàn hoàn hảo, như thể some_template<recurse>
không phải là bản trình bày mẫu hợp lệ, các bước trên sẽ không hoạt động. Một phiên bản lạ có các mẫu và đối số có khả năng được áp dụng, thì việc thay thế, sau đó là ứng dụng, sẽ được yêu cầu trong các trường hợp như vậy.
hiện đang sử dụng công cụ 'tự động'? – dwcanillas
@dwcanillas: Giống như trong [câu hỏi này] (http://stackoverflow.com/q/25338795/596781)? –
Um, tôi không chắc mình hiểu cách sử dụng tự động trong trường hợp này. Tôi phải khai báo kiểu và sau đó tự định nghĩa hàm này. –