2010-07-11 40 views
9

Tôi đã có này cho vòng lặp:chuyển đổi một vòng lặp for để một std :: for_each

std::vector<itemPtr>::iterator it; 
    for(it=items.begin(); it!=items.end(); ++it) 
    { 
     investigators.addToLeaderInventory(*it); 
    } 

Tôi muốn chuyển nó sang một cái gì đó như thế này:

std::for_each(items.begin(), items.end(), investigators.addToLeaderInventory); 

Tuy nhiên, đó dòng không biên dịch. g ++ cho tôi biết điều này:

error: no matching function for call to 
‘for_each(__gnu_cxx::__normal_iterator<std::tr1::shared_ptr<yarl::item::Item>*, 
std::vector<std::tr1::shared_ptr<yarl::item::Item>, 
std::allocator<std::tr1::shared_ptr<yarl::item::Item> > > >, 
__gnu_cxx::__normal_iterator<std::tr1::shared_ptr<yarl::item::Item>*, 
std::vector<std::tr1::shared_ptr<yarl::item::Item>, 
std::allocator<std::tr1::shared_ptr<yarl::item::Item> > > >, <unresolved overloaded 
function type>)’ 
/usr/include/c++/4.4/bits/stl_algo.h:4194: note: candidates are: _Funct 
std::for_each(_IIter, _IIter, _Funct) [with _IIter = 
__gnu_cxx::__normal_iterator<std::tr1::shared_ptr<yarl::item::Item>*, 
std::vector<std::tr1::shared_ptr<yarl::item::Item>, 
std::allocator<std::tr1::shared_ptr<yarl::item::Item> > > >, _Funct = void 
(yarl::party::Party::*)(yarl::itemPtr)] 

Khó đọc, để nói rằng ít nhất. Tôi tưởng tượng giải pháp là khá đơn giản, nhưng tôi không thể tìm ra những gì g + + là phàn nàn về. Chữ ký của investigators.addToLeaderInventory() là:

void ClassName::addToLeaderInventory(itemPtr item); 

nên làm việc với for_each, phải không? Tôi nên thay đổi điều gì?

+1

nếu bạn sẵn sàng sử dụng tăng cường, thực hiện foreach tuyệt vời, BOOST_FOREACH – Anycorn

Trả lời

8

for_each có một thực thể có thể gọi thuộc loại nào đó. Để gọi hàm thành viên trên đối tượng khác, bạn cần sử dụng mem_fun, kết thúc hàm thành viên để nó có thể được gọi là hàm bình thường, sau đó bạn cần ràng buộc nó với cá thể đối tượng mà nó được gọi bằng cách sử dụng bind1st:

std::for_each(items.begin(), items.end(), 
    std::bind1st(std::mem_fun(&ClassName::add), &investigators)); 

Một lựa chọn khác là sử dụng hiện đại hơn bind, mà thực hiện của bạn có thể cung cấp trong không gian tên std hoặc std::tr1 (nếu không, bạn có thể sử dụng the implementation from Boost):

using std::placeholders::_1; 

std::for_each(items.begin(), items.end(), 
    std::bind(&ClassName::add, &investigators, _1); 
+0

Đây là những gì tôi đang tìm kiếm. Cảm ơn. – Max

2

C++ không thể liên kết đối tượng và phương thức với nhau thành một "hàm" có thể gọi được. Bạn phải thực hiện ràng buộc một cách rõ ràng, hoặc thông qua một đối tượng có tùy chỉnh operator() ...

class AddToLeaderInventory { 
public: 
    AddToLeaderInventory(party::Party& party) : party_(party) { } 

    void operator()(item::Item& i) { party_.addToLeaderInventory(i); } 

private: 
    party::Party& party_; 
}; 
... 
std::for_each(items.begin(), items.end(), AddToLeaderInventory(investigators)); 

... hoặc sử dụng thư viện như Boost.Bind.

1

Nếu bạn có lambdas thì bạn có thể làm

for_each(items.begin(), items.end(), 
     [&](const ItemPtr& it) {investigators.addToLeaderInventory(it);}); 
Các vấn đề liên quan