2009-10-27 28 views
6

Nếu tôi có một đối tượng như thế này:Tăng chứa đa-index với chỉ số dựa trên giá trị lồng nhau

struct Bar { 
    std::string const& property(); 
}; 

tôi có thể tạo một container đa-index cho nó như thế này:

struct tag_prop {}; 
typedef boost::multi_index_container< 
    Bar, 
    boost::multi_index::indexed_by< 
     boost::multi_index::ordered_non_unique< 
      boost::multi_index::tag<tag_prop>, 
      boost::multi_index::const_mem_fun< 
       Bar, const std::string&, &Bar::property 
      > 
     > 
    > 
    , ... other indexes 
> BarContainer; 

Nhưng nếu tôi có một lớp học như thế này:

struct Foo { 
    Bar const& bar(); 
}; 

Làm cách nào tôi có thể xây dựng chỉ mục trên .bar().property() cho vùng chứa Foo đối tượng?

Thông thường tôi sẽ lồng các cuộc gọi đến boost::bind, nhưng tôi không thể tìm ra cách làm cho nó hoạt động trong ngữ cảnh của vùng chứa nhiều chỉ mục.

Trả lời

5

Tôi tin rằng bạn cần phải tạo một đối tượng vị ngữ có hai trường hợp của Foo và toán tử của nó() có thể gọi Foo :: bar() trên cả hai trường hợp.

Something như

struct MyPredicate 
{ 

    bool operator() (const Foo& obj1, const Foo& obj2) const 
    { 
     // fill in here 
    } 
}; 

và sau đó sử dụng

... 
boost::multi_index::ordered_unique<boost::multi_index::tag<tag_prop>, 
    boost::multi_index::identity<Foo>, MyPredicate>, 
... 

Check-out MultiIndex Ordered indices reference

+0

Perfect, cảm ơn bạn. –

1

Như nhiều như tôi thích sử dụng lambdas để làm những việc đơn giản, điều này có thể nhanh chóng bị thoái hóa :)

Trong trường hợp của bạn, vì nó phức tạp hơn một chút, tôi sẽ quay lại hoặc là trên một hàm miễn phí hoặc một bộ so sánh vị ngữ. .

Các vị có lợi thế là xác định loại rõ ràng hơn vì vậy nó thường dễ dàng hơn để thực sự mang nó trong

Ngoài ra, vì khả năng đọc, tôi thường typedef chỉ số của tôi, mang đến cho:

namespace mi = boost::multi_index; 

struct FooComparator 
{ 
    bool operator()(Foo const& lhs, Foo const& rhs) const 
    { 
    return lhs.bar().property() < rhs.bar().property(); 
    } 
}; 

typedef mi::ordered_unique < 
      mi::tag<tag_prop>, 
      mi::identity<Foo>, 
      FooComparator 
     > foo_bar_index_t; 

typedef boost::multi_index_container < 
      Foo, 
      mi::indexed_by < 
      foo_bar_index_t, 
      // ... other indexes 
      > 
     > foo_container_t; 

Cách tiếp cận vị ngữ yêu cầu mã bản mẫu nhiều hơn, nhưng nó cho phép tách biệt độc đáo logic so sánh khỏi định nghĩa chỉ mục, được tách biệt khỏi định nghĩa vùng chứa.

Phân tách rõ ràng giúp dễ dàng xem nhanh cấu trúc hơn.

+0

Đồng ý. Tôi thường sử dụng typedefs và bí danh không gian tên là tốt, nhưng nó dường như quá phức tạp cho ví dụ tầm thường này, vì vậy tôi đã thu gọn chúng thành một khai báo duy nhất. –

6

Thay vì cung cấp một so sánh người dùng định nghĩa, bạn có thể viết một người dùng định nghĩa chìa khóa vắt:

 
struct FooBarPropertyExtractor 
{ 
    typedef std::string result_type; 
    const result_type& oeprator()(const Foo& f) 
    { 
    return f.bar().property(); 
    } 
}; 

... 

typedef boost::multi_index_container< 
     Bar, 
     boost::multi_index::indexed_by< 
       boost::multi_index::ordered_non_unique< 
         boost::multi_index::tag<tag_prop>, 
         FooBarPropertyExtractor 
       > 
     > 
     , ... other indexes 
> FooContainer; 

Xem Advanced features of Boost.MultiIndex key extractors

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