2013-08-20 63 views
5

Có, hoặc bạn sẽ viết như thế nào, một lớp metafunction kiểm tra xem một lớp có tương thích với boost::range không? Tôi muốn sử dụng boost::enable thành ngữ, một cái gì đó giống nhưMetafunction để kiểm tra xem đối tượng có tương thích với phạm vi tăng

template <typename T> 
Constructor::Constructor(const T& t, __attribute__((unused)) typename boost::enable_if<is_range_compatible<T> >::type* aux=NULL) 

cho một is_range_compatible metafunction thích hợp. Tôi biết về is_container từ pretty_print, chụp rất nhiều trường hợp, nhưng không phải mọi thứ hoạt động với boost::range.

Chỉnh sửa Điều này đang sử dụng C++ 03, vì vậy tôi không có quyền truy cập vào các tính năng C++ 11. Tôi đang sử dụng cũ, gcc 4.1 và tăng 1.51.

+0

Boost đã có một giải pháp: [. các khái niệm kiểm tra] (http://www.boost.org/doc/ libs/1_54_0/libs/range/doc/html/range/concepts/concept_checking.html) – jrok

+1

Dường như tương tự như [câu hỏi này] (http://stackoverflow.com/questions/14439479/detecting-whether-something-is -boost-range-with-sfinae) – llonesmiz

+0

Bạn có quyền truy cập vào C++ 11 hay không? Bởi vì meta-lập trình là hơi dễ dàng hơn với 'decltype' và trả về muộn. –

Trả lời

0

Bạn có nghĩa là enable_if?

Nếu bạn có thể thuyết phục kiểm tra khái niệm Tăng cường hoạt động hữu ích với nó (thay vì macro biên dịch macro hiện đang sử dụng), hãy kiểm tra như ForwardConceptRangealready provided.

Nếu không, có vấn đề khi sử dụng macro BOOST_CONCEPT_ASSERT hiện tại thay thế không?

+0

Tôi muốn sử dụng SFINAE (tên tôi chỉ học được khi thấy bản sao được đề xuất), mà tôi không nhận được với các xác nhận. Một trong những điều tốt đẹp về 'boost :: range' là nó có thể lấy những thứ như các cặp lặp, mà tôi sẽ không làm việc với các kiểm tra khái niệm tăng cường, mặc dù tôi không hiểu chúng rất tốt. –

+0

Cụ thể là một bộ kiểm tra khái niệm tăng cường cho các phạm vi, tôi sẽ thêm một liên kết. Mặc dù, như tôi đã nói, chúng dường như không hoạt động ra khỏi hộp với SFINAE. – Useless

+0

... được thực hiện, mặc dù tôi vừa nhận thấy jrok đã cung cấp cùng một liên kết. Nếu 'has_range_const_iterator' làm việc cho bạn, nó sẽ dễ dàng hơn. – Useless

0

Nếu bạn nâng cấp lên Boost 1.54, có một thư viện tốt được gọi là TTI. Nó cho phép bạn soạn thảo các đặc điểm kiểu nội suy trong các hàm meta theo ý muốn, để bạn có thể dễ dàng tách ra các thuộc tính meta của riêng bạn mà có thể được sử dụng để bật hoặc tắt các mẫu chức năng. Mặc dù nó là một bài tập lập trình meta tốt đẹp, tôi không khuyên bạn nên làm điều đó trong mã sản xuất. Tôi thấy khó có thể nắm bắt được "các âm bản sai" phát sinh từ các chi tiết thực hiện của các container STL. Ví dụ, các thùng chứa liên kết đến với MSVC11 kế thừa các hàm beginend thành viên của chúng từ một lớp cơ sở mang lại giá trị âm sai với các biến vị ngữ meta được tạo thông qua BOOST_TTI_HAS_MEMBER_FUNCTION. Mặc dù biệt danh của anh ta, Useless đã cho bạn một lời khuyên tốt: Sử dụng các khái niệm đi kèm với Boost.Range để từ chối hoặc chấp nhận kiểu bên trong phần thân của mẫu chức năng như hàm tạo trong ví dụ của bạn ... Tất nhiên, điều này sẽ không giải quyết được vấn đề chuyển đổi cho Constructor của bạn ...

EDIT: Ví dụ, lấy từ vex:

#include <boost/tti/has_member_function.hpp> 
#include <vector> 
#include <map> 

namespace tti_test { 
    BOOST_TTI_HAS_MEMBER_FUNCTION(begin); 

    // .. begin test class for mstest 

    // this succeeds in both variants 
    TEST_METHOD(has_const_member_function_begin_is_true_for_vector) 
    { 
     Assert::IsTrue(has_member_function_begin< 
      std::vector<int>::const_iterator (std::vector<int>::*)() const 
     >::value); 

     Assert::IsTrue(has_member_function_begin< 
      const std::vector<int>, std::vector<int>::const_iterator 
     >::value); 
    } 

    // this fails in both variants... 
    TEST_METHOD(has_const_member_function_begin_is_true_for_map) 
    { 
     Assert::IsTrue(has_member_function_begin< 
      std::map<int, int>::const_iterator (std::map<int, int>::*)() const 
     >::value); 

     Assert::IsTrue(has_member_function_begin< 
      const std::map<int, int>, std::map<int, int>::const_iterator 
     >::value); 
    } 

    // end test class for mstest 
}