2013-06-19 26 views
11

Có một (dường như) đẹp cách C++ 03 tìm hiểu xem một loại có một chức năng thành viên hoặc điều hành:C++ 11 cách tìm kiếm nếu một loại có chức năng thành viên hoặc hỗ trợ toán tử?

https://github.com/jaredhoberock/is_call_possible/blob/master/is_call_possible.hpp

Có không hiện đại C++ 11 cách để làm điều này? Sẽ tốt hơn nếu không bao gồm bất kỳ mã bên ngoài nào và chỉ sử dụng tiêu chuẩn.

+0

Có mục đích nào cho câu hỏi hoặc bạn chỉ tò mò – aaronman

Trả lời

2

Không, nó cũng tương tự như vậy. Nhiều hơn hoặc ít hơn. Triển khai khác nhau, mặc dù bạn có thể thay thế một số các metafunctions được sử dụng trong nội bộ bằng cách thực hiện đó với các đặc điểm thư viện chuẩn. Nhưng không có cách nào đơn giản cách phát hiện nếu bạn có thể gọi hàm trên một số loại nhất định cho một số bộ đối số.

Đó là dành cho concepts (PDF).

19

này làm việc với tất cả các trường hợp thử nghiệm được đưa ra trong GitHub (Demo: http://ideone.com/ZLGp4R):

#include <type_traits> 

template <typename C, typename F, typename = void> 
struct is_call_possible : public std::false_type {}; 

template <typename C, typename R, typename... A> 
struct is_call_possible<C, R(A...), 
    typename std::enable_if< 
     std::is_same<R, void>::value || 
     std::is_convertible<decltype(
      std::declval<C>().operator()(std::declval<A>()...) 
      //    ^^^^^^^^^^ replace this with the member you need. 
     ), R>::value 
    >::type 
> : public std::true_type {}; 
16

C++ 11 cho biết thêm một thủ thuật mới, mà tôi thường đùa gọi là "CFINAE" (biên soạn thất bại không phải là một lỗi) .

Nó sử dụng toán tử decltype và các thuộc tính thông thường của SFINAE.

Hãy xem xét các chức năng sau:

template <typename X, typename Y> 
static auto check(X& x, Y& y) -> decltype(x >> y); 

Nó sẽ được xem xét trong quá quá tải chỉ khi XY là loại mà các nhà điều hành thay đổi được định nghĩa. Thêm tình trạng quá tải thông thường cho check và bạn có cơ chế kiểm tra xem có thể biên dịch một biểu thức tùy ý hay không.

Và thực sự, đây là nguyên tắc được phát triển trong thư viện thử nghiệm Origin bởi Andrew Sutton (một trong các tác giả của đề xuất Concepts Lite). Thực tế, ví dụ của tôi được lấy thẳng từ here để triển khai khái niệm Streamable.

Tôi khuyên bạn nên trình bày sau đây từ GoingNative 2012 bởi Andrew Sutton và Bjarne Stroustrup nơi họ đưa ra một giới thiệu về mới đi vào khái niệm và các thư viện Xuất xứ:

http://channel9.msdn.com/Events/GoingNative/GoingNative-2012/A-Concept-Design-for-C-

1

tôi sử dụng phương pháp nổi tiếng sau đây dựa trên SFINAE:

#define TYPE_SUPPORTS(ClassName, Expr)       \ 
    template<typename U>           \ 
    struct ClassName            \ 
    {               \ 
    private:              \ 
    template<typename>           \ 
    static constexpr std::false_type test(...);    \ 
                   \ 
    template<typename T = U>         \ 
    static decltype((Expr), std::true_type{}) test(int) ;  \ 
                   \ 
    public:              \ 
    static constexpr bool value = decltype(test<U>(0))::value; \ 
    }; 

Mục đích chính của macro là đơn giản hóa việc thêm kiểm tra loại. Macro xác định một lớp cho phép bạn thực hiện kiểm tra tùy ý cho một loại T.

Như một ví dụ, để kiểm tra xem std::begin() có thể được gọi cho một loại:

namespace detail 
{ 
    TYPE_SUPPORTS(SupportsBegin, std::begin(std::declval<T>())) 
} 

template<typename T> 
bool supportsBegin() 
{ 
    return detail::SupportsBegin<T>::value; 
} 

Tất nhiên, detail namespace và chức năng bao bọc đều đường cú pháp, nhưng cải thiện cú pháp một chút về phía người gọi .

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