2011-11-28 39 views
5

Giả sử nếu tôi có điều này,Quy tắc xác định tập hợp loại chức năng tương thích với std :: function <R(T1,T2)>?

std::function<int(int,int)> fs; 

thì làm sao tôi có thể xác định tập hợp các hàm (hoặc đối tượng chức năng) mà fs có thể được khởi tạo với?

nào của folllowing được phép và không:

std::function<int(int,int)> fs = [](int, int) { return int(10); }; 
std::function<int(int,int)> fs = [](char, char) { return char(10); }; 
std::function<int(int,int)> fs = [](int, short) { return int(10); }; 
std::function<int(int,int)> fs = [](double, int) { return float(10); }; 
std::function<int(int,int)> fs = [](int, wchar_t) { return wchar_t(10); }; 

std::function<int(int,int)> fs = [](const char*, int){ return "string"; }; 
std::function<int(int,int)> fs = [](const char*, int){ return 10; }; 
std::function<int(int,int)> fs = [](const char*, int){ return std::string(); }; 

Tất nhiên, tôi có thể biên dịch và xem cái nào biên dịch tốt, và đó không. Nhưng điều đó không giúp tôi hiểu các biến thể trong các loại tham số và kiểu trả về. Làm thế nào đến nay tôi có thể sử dụng các loại khác nhau cho họ?

Nói cách khác, nếu tôi đã đưa ra một hàm (hoặc đối tượng hàm), làm thế nào tôi có thể xác định tại thời gian biên dịch nếu nó tương thích với std::function<int(int,int)> hay không? Tôi ít hiểu, nhưng tôi không đủ tự tin.

Vì vậy, hãy giúp tôi hiểu và đặt ra các quy tắc để xác định tập hợp loại chức năng tương thích với std::function<R(T1,T2)>? Metaprogramming có thể giúp tôi ở đây để thông báo cho người dùng, tạo ra các thông báo lỗi hay không, nếu họ sử dụng chức năng không tương thích?

Bằng cách này, nhóm đầu tiên có vẻ là tương thích: http://ideone.com/hJpG3

Trả lời

4

Đối tượng (con trỏ hàm hay functor) phải Callable với các loại tranh luận nhất định, ví dụ: fun(declval<Types>() ...) là tốt được hình thành và mặc nhiên chuyển đổi thành R.

Xem C++ 11 §20.8.2 nói riêng; nó đưa ra các trường hợp đặc biệt khác nhau cho các con trỏ tới các thành viên, vv §20.8.11.2/2 và 20.8.11.2.1/7 kết hợp điều này với nhà xây dựng std::function.

4

Không có giải pháp lập trình meta được đóng gói sẵn. Tôi đã lập trình các đặc điểm sau để trợ giúp với câu hỏi này. Những đặc điểm này đơn giản thực hiện các phần được đề cập trong câu trả lời của Potatoswatter. Các bình luận mã thậm chí liệt kê các điểm bullet trong các phần được tham chiếu.

template <class _F, class ..._Args> struct __invokable; 
template <class _F, class ..._Args> struct __invoke_of; 

http://llvm.org/svn/llvm-project/libcxx/trunk/include/type_traits

Tôi đã sử dụng chúng để tạo ra một tin "thành viên đặc điểm" của std::function:

template <class _F, bool = __invokable<_F&, _ArgTypes...>::value> 
    struct __callable; 

http://llvm.org/svn/llvm-project/libcxx/trunk/include/functional

Nó đã xảy ra với tôi rằng những có thể làm cho tốt tài liệu tr2 (sans các dấu gạch dưới hàng đầu). Nếu bạn đồng ý, có lẽ bạn nên cho đại diện Cơ quan Quốc gia của bạn biết.

Nếu bạn muốn sử dụng những đặc điểm này, mã là mã nguồn mở. Nhưng tôi sẽ đánh giá cao nếu bạn tôn trọng giấy phép nguồn mở bằng cách bao gồm thông tin bản quyền trong mỗi tệp.

+0

Có vẻ như câu trả lời này nằm trong ngữ cảnh chức năng mà Thư viện chuẩn đưa ra ... nếu câu trả lời của tôi không chính xác, bạn có thể nhận xét về lý do không? Chỉnh sửa - đặc điểm này dường như bỏ qua việc chuyển đổi giá trị trả về… – Potatoswatter

+0

@Potatoswatter: Tôi vừa xem xét việc thực hiện các đặc điểm này. Chúng phụ thuộc vào 'std :: forward',' std :: is_convertible' và 'std :: is_same'. Chúng có thể được thực hiện như một phần của std :: lib hay không.Tôi cũng đã xem xét câu trả lời của tôi và không thấy nơi tôi ngụ ý rằng câu trả lời của bạn không chính xác. Câu trả lời của tôi chỉ đơn giản là cung cấp việc thực hiện lập trình meta cho các phần mà bạn đề cập đến. OP hỏi về một giải pháp lập trình meta, vì vậy tôi nghĩ câu trả lời của tôi có liên quan. Về việc chuyển đổi giá trị trả về: Điều này được bao hàm trong '__callable' bằng cách sử dụng' __invoke_of' và 'is_convertible'. –

+1

OK. Sự bất đồng duy nhất sẽ là tôi xem xét câu trả lời của tôi là "câu trả lời chuẩn được đóng gói sẵn". Đối với chuyển đổi kiểu trả về, tôi đã không theo liên kết và giả định nó là một mẫu không phải là thành viên, không có quyền truy cập vào kiểu trả về mong muốn. Ở cấp độ người dùng, không phải là 'std :: is_convertible :: type, R> :: value' đủ? Tôi đoán nó phụ thuộc nếu bạn muốn SFINAE hoặc kết quả 'sai'. – Potatoswatter

Các vấn đề liên quan