First, many thanks to Peter Dimov for answering my earlier questions. I've gotten hung up on something that may not be directly related to shared_ptr, but it's in the mix here. I suspect the real problem is my lack of experience using the STL algorithms, but I'm making an effort not to go back to writing my own loops with this project. Using my Widget theme, here's what I've got. A WidgetManager class contains a stl::list of shared_ptr<Widget> objects. It also contains a stl::vector of shared_ptr<WidgetMap> objects. WidgetMap objects contain a B+tree. (I know, I should probably change this to stl::map or multimap, I'll do that later) The index maps a data member of a Widget to a shared_ptr to the Widget for fast lookups. It is possible that new data members can be added or removed from the Widgets, and we have functions for handling that. Additional WidgetMap objects are added to the WidgetManager for Widget data members as needed. When adding a new WidgetMap, I need to loop through the existing set of Widgets and add them to the new WidgetMap. This is the simplest example I can think of as to what I'm trying to do, however obviously this does not work... void WidgetManager::addMap(const WidgetMapPtr i){ maps_.push_back(i); // have to write a function adapter here? for_each(widgetset_.begin(),widgetset_.end(),i->insert); } Along a similar line, when a Widget's data member collection is changed, I need to remove any WidgetMap objects fromm the WidgetManager that referenced the member being deleted. void WidgetManager::dropWidgetMember(const DataMemberPtr d){ // delete any maps using the target member // how to fix this bloody line? getIndexedMember returns a DataMemberPtr to the member it is keyed on. maps_.erase(remove_if(maps_.begin(),maps_.end(),(boost::mem_fn(&WidgetMap::getIndexedMember)).equals(d))); // get rid of the member itself members_.erase(remove_if(members_.begin(),members_.end(),boost::bind(&DataMember::equals,_1,d))); // rewrite the data file, we're all dirty anyway. this->compact(); } I feel like I understand what I want to do, but I cannot find a reference that explains how to do it the 'correct' way. At least not that I can grasp. Can someone point me in the right direction? Thanks, Mark
From: "someuserat"
void WidgetManager::addMap(const WidgetMapPtr i){ maps_.push_back(i); // have to write a function adapter here? for_each(widgetset_.begin(),widgetset_.end(),i->insert); }
I think that you need bind(&WidgetMap::insert, i, _1) here. [...]
void WidgetManager::dropWidgetMember(const DataMemberPtr d){
// delete any maps using the target member // how to fix this bloody line? getIndexedMember returns a DataMemberPtr to the member it is keyed on.
maps_.erase(remove_if(maps_.begin(),maps_.end(),(boost::mem_fn(&WidgetMap::g etIndexedMember)).equals(d))); This is getting harder. bind(&DataMember::equals, bind(&WidgetMap::getIndexedMember, _1), d) would be my guess. Easier would be to define a helper function bool memberEquals(WidgetMap const & m, DataMemberPtr d) { return m.getIndexedMember().equals(d); } and then use bind(memberEquals, _1, d) in dropWidgetMember.
--- In Boost-Users@y..., "Peter Dimov"
for_each(widgetset_.begin(),widgetset_.end(),i->insert); }
I think that you need bind(&WidgetMap::insert, i, _1) here.
Thanks! I figured that one out this morning, [...]
maps_.erase(remove_if(maps_.begin(),maps_.end(),(boost::mem_fn (&WidgetMap::g etIndexedMember)).equals(d)));
This is getting harder.
bind(&DataMember::equals, bind(&WidgetMap::getIndexedMember, _1), d)
would be my guess. Easier would be to define a helper function
bool memberEquals(WidgetMap const & m, DataMemberPtr d) { return m.getIndexedMember().equals(d); }
and then use
bind(memberEquals, _1, d) in dropWidgetMember.
I actually ended up figuring out how to write a function object class to do something similar. This has been a good learning experience! Is there a down side to the function object approach over the helper function? From what I could tell, the helper function had to be a global function, which just didn't seem right. Thanks, Mark
--- At Fri, 20 Sep 2002 01:28:18 +0000, someuserat wrote:
I actually ended up figuring out how to write a function object class to do something similar. This has been a good learning experience! Is there a down side to the function object approach over the helper function? From what I could tell, the helper function had to be a global function, which just didn't seem right.
I recall reading an article a few months ago that seemed to indicate that under some circumstances function objects provide more of an opportunity for inlining. Depending on how the function is used, the compiler may need to pass the reference as a pointer to a function. In this case, the function will likely not be inlined. With a function object, the function "pointer" is really a reference to a zero-length object that has a function method. Calling this method will likely be inlined. As I recall the opportunities became significant using the binding functions. I think under many circumstances this is also true for boost::bind. ...Duane
From: "someuserat"
This is getting harder.
bind(&DataMember::equals, bind(&WidgetMap::getIndexedMember, _1), d)
would be my guess. Easier would be to define a helper function
bool memberEquals(WidgetMap const & m, DataMemberPtr d) { return m.getIndexedMember().equals(d); }
and then use
bind(memberEquals, _1, d) in dropWidgetMember.
I actually ended up figuring out how to write a function object class to do something similar. This has been a good learning experience! Is there a down side to the function object approach over the helper function? From what I could tell, the helper function had to be a global function, which just didn't seem right.
The two approaches are about equal. The function object requires slightly more effort since you need boilerplate code to hold the state ('d' in the example); boost::bind is good at holding state. The function object is also less flexible, the function is more likely to be reusable in other contexts. On the other hand the function will typically not be inlined, although this is rarely a concern. Of course you can use a stateless function object similar to 'memberEquals', too. Both the function and the helper class can be defined in an unnamed namespace; the function can be made static. Neither is more global than the other, so this is not a deciding factor. You can make the function member of WidgetMap, too, if you prefer the OO style, although this is a bit controversial. :-) boost::bind just gives you more options; it's up to you to choose what works best.
participants (3)
-
Duane Murphy
-
Peter Dimov
-
someuserat