| Topic: |
DEVELOP > c-Plus-Plus |
| User: |
"Icosahedron" |
| Date: |
21 Dec 2003 04:00:24 AM |
| Object: |
call_with_second |
I am using a hash_map (not exactly standard, I understand) and
want to use for_each to call a member function on the class of
the data_type in the hash_map. After doing a search in Google
groups and web archives, I couldn't find what I wanted, so this
is what I came up with.
It works well for what I want, but I'd like some feedback on it
before canonizing it for my own little utility library.
Problem: I have a hash_map that references hardware specific
handles (COM objects) to hardware independent buffers (pointers):
std::hash_map<void*, IDirect3DVertexBuffer9*> s_dx9VertexBuffers;
Later, as I'm cleaning up, I would like to call a method on these
buffers. In the above example,
IDirect3DVertexBuffer9::Release(), so I attempted something like:
std::for_each( s_dx9VertexBuffers.begin(),
s_dx9VertexBuffers.end(),
std::mem_fun( &IDirect3DVertexBuffer9::Release ));
Of course this didn't work, because the iterators return
std::pairs of the key and data_type types. Having to do this
with a number of different types, I simply whipped up a simple
adaptor that called Release in the operator(). Then I had to
copy and paste it a few times. A little while later I came up
with this to parameterize it:
template <typename Func>
struct call_with_second_t {
Func _f;
explicit call_with_second_t( Func f ) : _f(f) {}
template <typename A, typename B>
inline void operator()( const std::pair<A,B>& v ) const {
const B& value = v.second;
_f( value );
}
};
template <typename Func>
call_with_second_t<Func> call_with_second( Func f )
{
return call_with_second_t<Func>( f );
}
This achieves exactly what I want it to, namely:
std::for_each( s_dx9VertexBuffers.begin(),
s_dx9VertexBuffers.end(),
call_with_second( boost::mem_fn(
&IDirect3DVertexBuffer9::Release ));
with only the minor inconvenience of using call_with_second
adaptor. (I used boost::mem_fn because it knows about __stdcall
used in COM).
What I would like to know is there a better way of doing this
that is already
in the standard? I saw select2nd, but that didn't seem to work,
at least not that I could get it to.
Any comments appreciated.
.
|
|
| User: "Thomas Wintschel" |
|
| Title: Re: call_with_second |
21 Dec 2003 11:35:13 AM |
|
|
"Icosahedron" <noone@nowhere.com> wrote in message
news:YaeFb.504646$0v4.21748980@bgtnsc04-news.ops.worldnet.att.net...
I am using a hash_map (not exactly standard, I understand) and
want to use for_each to call a member function on the class of
the data_type in the hash_map. After doing a search in Google
groups and web archives, I couldn't find what I wanted, so this
is what I came up with.
It works well for what I want, but I'd like some feedback on it
before canonizing it for my own little utility library.
Problem: I have a hash_map that references hardware specific
handles (COM objects) to hardware independent buffers (pointers):
std::hash_map<void*, IDirect3DVertexBuffer9*> s_dx9VertexBuffers;
Later, as I'm cleaning up, I would like to call a method on these
buffers. In the above example,
IDirect3DVertexBuffer9::Release(), so I attempted something like:
std::for_each( s_dx9VertexBuffers.begin(),
s_dx9VertexBuffers.end(),
std::mem_fun( &IDirect3DVertexBuffer9::Release ));
Of course this didn't work, because the iterators return
std::pairs of the key and data_type types. Having to do this
with a number of different types, I simply whipped up a simple
adaptor that called Release in the operator(). Then I had to
copy and paste it a few times. A little while later I came up
with this to parameterize it:
template <typename Func>
struct call_with_second_t {
Func _f;
explicit call_with_second_t( Func f ) : _f(f) {}
template <typename A, typename B>
inline void operator()( const std::pair<A,B>& v ) const {
const B& value = v.second;
_f( value );
}
};
template <typename Func>
call_with_second_t<Func> call_with_second( Func f )
{
return call_with_second_t<Func>( f );
}
This achieves exactly what I want it to, namely:
std::for_each( s_dx9VertexBuffers.begin(),
s_dx9VertexBuffers.end(),
call_with_second( boost::mem_fn(
&IDirect3DVertexBuffer9::Release ));
with only the minor inconvenience of using call_with_second
adaptor. (I used boost::mem_fn because it knows about __stdcall
used in COM).
What I would like to know is there a better way of doing this
that is already
in the standard? I saw select2nd, but that didn't seem to work,
at least not that I could get it to.
Any comments appreciated.
select2nd will work but you also need compose1:
(untested for obvious reasons)
std::for_each( s_dx9VertexBuffers.begin(), s_dx9VertexBuffers.end(),
std::compose1( std::mem_fun( &IDirect3DVertexBuffer9::Release ),
std::select2nd< std::hash_map<void*,
IDirect3DVertexBuffer9*>::value_type >()));
select2nd and mem_fun are both function adapters. for_each requires a
single adapter. compose1 is a function adapter takes the output of its
second argument and feeds it to the first.
Tom
.
|
|
|
|

|
Related Articles |
|
|