Call member functions of container element elements with for_each parameter?

Having mixed up the title, we hope that some code will clarify:

struct MyNestedType { void func(); }; struct MyType { MyNestedType* nested; } std::vector<MyType> vec; // ... populate vec // I want something approximating this line, but that doesn't use made-up C++! std::for_each(vec.begin(), vec.end(), std::mem_fun_ref(&MyType::nested->func)); 

So basically I want to call a method for each element of the container, but it's not actually a type method, it's some kind of method for the contained type ... I know that I could write a function object to 'pass' the call, but there is a few methods that I would call, and that will be messy.

Any ideas?

+4
source share
6 answers

You can use such a functor

 template <typename T, T* MyType::* TMember, void (T::* TNestedMember)() > struct Caller { Caller() { } template <typename TObject> void operator()(TObject object) { (object.*TMember->*TNestedMember)(); } }; 

To solve your problem

 struct MyNestedType { MyNestedType(int a): a_(a){ } void func() { std::cout << "MyNestedType::func " << a_ << std::endl; } void foo() { std::cout << "MyNestedType::foo " << a_ << std::endl; } int a_; }; struct MyType { MyNestedType* nested; }; int main() { std::vector<MyType> vec; std::auto_ptr<MyNestedType> nt1(new MyNestedType(2)); std::auto_ptr<MyNestedType> nt2(new MyNestedType(5)); MyType t1 = {nt1.get()}; MyType t2 = {nt2.get()}; vec.push_back(t1); vec.push_back(t2); std::for_each(vec.begin(), vec.end(), Caller<MyNestedType, &MyType::nested, &MyNestedType::func>()); std::for_each(vec.begin(), vec.end(), Caller<MyNestedType, &MyType::nested, &MyNestedType::foo>()); } 
+3
source

Why don't you just use a simple for loop?

 for(vector<MyType>::iterator i = vec.begin(); i != vec.end(); ++i) i->nested->func(); 

Alternatively, you can use lambda expressions or boost :: foreach

 FOREACH(MyType x, vec) x.nested->func(); 

You can create your expression using attachments and mem_funs, but it will become very dirty and confusing! There is no advantage to putting everything in one line of std :: foreach.

+6
source

Maybe you can add func () to struct MyType ():

 void func(...) { nested->func(...); } 

Thus, you will not have a separate adapter functor, but instead there will be aggregation inside the wrapper type, i.e. a fairly regular OOP technique.

+2
source

If you want to use for_each, you need a functor.

 struct CallMyFunc { void operator()(MyType& obj) { obj.nested->func();} }; std::for_each(vec.begin(), vec.end(), CallMyFunc()); 

As an alternative, I would use the boost :: FOREACH syntax described:

Dario: Member member member container element functions with for_each?

+2
source

Yes, boost::bind can be used for this, but it becomes messy. Please use @Dario boost for each method, but here is boost::bind one for completeness

 std::for_each(vec.begin(), vec.end(), boost::bind(&MyNestedType::func, boost::bind(&MyType::nested, _1))); 

In any case, as it happens, we don’t even get a nice one-line with this :)

+2
source

How about using boost transform_iterator ?

0
source

All Articles