call_with_second

I

Icosahedron

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.
 
T

Thomas Wintschel

Icosahedron said:
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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,156
Messages
2,570,878
Members
47,408
Latest member
AlenaRay88

Latest Threads

Top