2010-02-22 27 views
8

Tôi có bản đồ lưu trữ cấu trúc đơn giản với khóa. Cấu trúc có hai hàm thành viên, một là hàm khác không phải. Tôi đã quản lý gọi hàm const bằng cách sử dụng std :: for_each mà không có bất kỳ vấn đề nào, nhưng tôi có một số vấn đề gọi hàm không const.Boost.Bìm cách truy cập std :: các yếu tố bản đồ trong tiêu chuẩn :: for_each

struct MyStruct { 
    void someConstFunction() const; 
    void someFunction(); 
}; 

typedef std::map<int, MyStruct> MyMap; 
MyMap theMap; 

//call the const member function 
std::for_each(theMap.begin(), theMap.end(), 
    boost::bind(&MyStruct::someConstFunction, boost::bind(&MyMap::value_type::second, _1))); 

//call the non-const member function 
std::for_each(theMap.begin(), theMap.end(), 
    boost::bind(&MyStruct::someFunction, boost::bind(&MyMap::value_type::second, _1))); 

Các cuộc gọi đến hàm thành viên const hoạt động tốt, nhưng có vẻ như đẩy mạnh nội hy vọng một MyStruct const nơi nào đó, và do đó không thành công với các lỗi biên dịch sau trong MSVC7.1.

tăng \ bind \ mem_fn_template.hpp (151): lỗi C2440: 'tranh luận': không thể chuyển đổi từ 'MyStruct const * __ w64' thành 'MyStruct * const'

Tôi đánh giá cao bất kỳ giúp làm thế nào để thiết lập các thông số mẫu một cách chính xác, do đó, ràng buộc không nhận ra các thông số một cách chính xác và để tôi gọi hàm không const.

cảm ơn, Carl

+0

Nếu bạn sao lưu và cho chúng tôi biết những gì bạn đang thực sự muốn thực hiện ở đây thì sao?Sử dụng for_each với một bản đồ với boost :: bind * có thể * là hợp lý, nhưng rất có thể là một cách tiếp cận chung khác sẽ làm việc tốt hơn (nhiều lần loại câu hỏi này phát sinh, đó là vì 'std :: for_each' là một lựa chọn tồi cho tình hình, và một cái gì đó như 'std :: copy' hoặc std :: accumulate' sẽ làm công việc đơn giản hơn nhiều). –

+0

Các MyStruct được sử dụng trong một loại hệ thống hạt, nơi MyStruct là hạt. Hàm const là một hàm draw(), hàm non-const tính toán vị trí mới. Khóa trong bản đồ là ngày tạo. Dù sao, tại thời điểm tôi đăng câu hỏi đó là nhiều hơn về cách để làm cho công việc đó hơn nếu đây là một thiết kế tốt trong đầu. – Carl

Trả lời

8

IIRC, Boost.Bind sử dụng boost::mem_fn để gắn kết với khả năng của thành viên. Bây giờ, nếu bạn nhìn vào mem_fun (cuộn xuống phần // data member support), bạn sẽ thấy rằng nó đã gõ result_type của nó như là một const &, trong khi vẫn còn quá tải của toán tử gọi hàm hỗ trợ khai thác của một thành viên không phải từ một đối số không const.

Do đó, có vẻ như vấn đề là điều này gây nhầm lẫn cơ chế khấu trừ loại Boost.Bind. Do đó, một giải pháp sẽ cho Bind biết rõ ràng rằng kết quả không phải là const:

//call the non-const member function 
std::for_each(theMap.begin(), theMap.end(), 
    boost::bind(&MyStruct::someFunction, 
     boost::bind<MyStruct&>(&MyMap::value_type::second, _1) 
    ) 
); 
+0

+1 Đẹp thám tử làm việc. :-) Kỳ lạ, sử dụng 'boost :: lamba :: bind' sẽ biên dịch mà không chỉ định rõ kiểu trả về. Có lẽ 'boost :: lamda :: bind' là thông minh hơn' boost :: bind' trong việc suy ra các kiểu trả về? –

+0

Wow, cảm ơn bạn rất nhiều. Điều đó biên dịch tốt. Mặc dù tôi thích sử dụng Boost nhưng tôi vẫn rất khó đọc hầu hết mã của họ, vì vậy tôi đã thất bại. Cảm ơn bạn đã giúp đỡ. – Carl

+0

Tôi nghĩ bạn có nghĩa là 'boost :: mem_fn' – Manuel

0

Một vấn đề tôi phát hiện: các ràng buộc thứ hai được gọi cho một hàm thành viên không. thứ hai là thành viên dữ liệu, không phải là một phương pháp std :: cặp

+3

Tôi đã tìm thấy kỹ thuật này trong bài viết này: http://www.informit.com/articles/article.aspx?p=412354&seqNum=4 Nó tuyên bố "Bạn có thể liên kết với biến thành viên giống như bạn có thể với hàm thành viên , hoặc một chức năng miễn phí. Vì mã for_each về cơ bản giống nhau cho cả hai hàm thành viên và vấn đề chỉ gặp phải trong lời gọi hàm không phải thành viên, tôi đoán chính xác bài viết. – Carl

4

Nếu bạn đã phụ thuộc vào Boost, bạn có thể sẵn sàng để kiểm tra Boost Foreach

BOOST_FOREACH(MyMap::value_type const& val, MyMap) 
{ 
    val.second.someConstFunction(); 
} 

nhiều nhiều có thể đọc được, mặc dù tôi không biết về các vấn đề hiệu suất.

Cũng lưu ý rằng bạn không thể sử dụng rập khuôn gõ trong vĩ mô mà không "thoát" các , nhân vật:

  • hoặc bằng một typedef trước
  • hoặc bằng cách sử dụng một cặp thứ hai của ngoặc xung quanh các loại
+0

Tôi biết Boost Foreach và điều đó hoạt động tất nhiên. Nhưng tôi chỉ tò mò muốn tìm cú pháp chính xác cho giải pháp trên, vì mã ở trên hoạt động tốt cho hàm const và không thành công cho hàm không const. – Carl

+4

Tôi tin rằng mã chính xác sẽ là (xóa const nếu bạn muốn thay đổi các giá trị): BOOST_FOREACH (MyMap :: value_type const & val, theMap) {...} – Bklyn

+0

và bạn không phải liên kết để tăng khi sử dụng Boost.Bind hoặc Boost.Foreach –

7

Nếu bạn thấy mình cần phải làm điều này rất nhiều tôi khuyên bạn nên sử dụng thư viện Boost.RangeEx:

#include <boost/range/algorithm/for_each.hpp> 
#include <boost/range/adaptor/map.hpp> 
#include <boost/mem_fn.hpp> 
#include <map> 

struct MyStruct { 
    void someConstFunction() const; 
    void someFunction(); 
}; 

typedef std::map<int, MyStruct> MyMap; 
MyMap theMap; 

int main() 
{ 
    //call the const member function 
    boost::for_each(theMap | boost::adaptors::map_values, 
        boost::mem_fn(&MyStruct::someConstFunction)); 

    //call the non-const member function 
    boost::for_each(theMap | boost::adaptors::map_values, 
        boost::mem_fn(&MyStruct::someFunction)); 
} 

Nó đã được chấp nhận vào Boost nhưng chưa có bản phân phối chính thức. Cho đến khi bạn có thể, bạn có thể download it từ Boost Vault (liên kết tải xuống tệp zip).

+0

Điều đó có vẻ dễ đọc hơn và dễ hiểu hơn so với giải pháp liên kết. Nó chắc chắn có giá trị một cái nhìn gần hơn. Cảm ơn vì tiền hỗ trợ. – Carl

+0

@Carl - cũng lưu ý rằng boost :: mem_fn dễ sử dụng hơn boost :: bind trong trường hợp này là – Manuel

+0

Câu trả lời này là trực giao cho câu hỏi, nó thay thế vòng lặp 'std :: for_each' bằng' boost :: for_each', nhưng không nói cách sử dụng 'boost :: bind' làm đối số cho cả hai. Mặc dù vậy, nó cung cấp một workaround. –

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