Boost logo

Boost :

From: sanichin_at_[hidden]
Date: 2001-11-05 01:46:41

First, Peter thanks for a wonderful set of templates. I've wanted
something like this for a while, but haven't ever taken the
considerable amount of time and effort to implement it. Now I don't
have to.

You know someone is using your stuff when they request features...

My problem concerns calling conventions. Yes, I know these use
compiler-specific keywords. I'm asking for a general-case, compiler-
independent change to boost:mem_fn that will make dealing with this
compiler specific stuff easier.

For example, at least a couple Windows compilers support the
__stdcall calling convention, where the callee removes parameters
from the stack. The Win32 API and COM objects use this calling

A __stdcall member function pointer looks like this:
typedef void (__stdcall T::*SomeMemberFunctionPtr)();

I have a bunch of COM objects in a STL container. I want to use
std::for_each and boost::bind to call a method on all the objects in
the container. The method I want to call uses the __stdcall calling
convention. Thus it doesn't compile, because boost::bind expects

void (T::*)();

Which is how it should be.

But what I've had to do to solve the problem is basically re-
implement ALL of mem_fn.hpp, and implement my own bind function
templates. A simple generic, compiler-independent change to
boost::mem_fn could at least simplify the work of supporting compiler-
specific calling conventions.

The idea I used was to use a traits struct to specify the type of the
function pointer. This is best illustrated through code:

// ********* BEGIN CODE *********
namespace boost
// calling convention traits
template <class R, class T> struct mem_fun_traits_0
        typedef R (T::*mem_func_type)();
        typedef R (T::*const_mem_func_type)() const;

#if defined(_MSC_VER)
template <class R, class T> struct mem_fun_stdcall_traits_0
        typedef R (__stdcall T::*mem_func_type)();
        typedef R (__stdcall T::*const_mem_func_type)() const;

namespace _mfexi // mem_fun_ex_impl
// mf0

template<class R, class T, class F=typename mem_fun_traits_0<R,
T>::mem_func_type >
class mf0

    typedef R result_type;
    typedef T * first_argument_type;

    F f_;


} // namespace _mfexi

#if defined(_MSC_VER)
template<class R, class T> _mfexi::mf0<R, T, typename
mem_fun_stdcall_traits_0<R, T>::mem_func_type>
mem_fn_ex(R (__stdcall T::*f)())
        return _mfexi::mf0<R, T,mem_fun_stdcall_traits_0<R,

// define new bind templates
// 0
template<class R, class T,
    class A1>
    _bi::bind_t<R, _mfexi::mf0<R, T, typename
mem_fun_stdcall_traits_0<R, T>::mem_func_type>, typename
    BOOST_BIND(R (__stdcall T::*f) (), A1 a1)
    typedef _mfexi::mf0<R, T, mem_fun_stdcall_traits_0<R,
T>::mem_func_type> F;
    typedef typename _bi::list_av_1<A1>::type list_type;
    return _bi::bind_t<R, F, list_type>(F(f), list_type(a1));
#endif // _MSC_VER
} // namespace boost
// ******** END CODE ************

By using the traits class, I can easily reuse the same member
function class implementation for a varied number of calling
conventions. The original mem_fn function templates and bind
templates remain unmodified for the default calling convention case.

It's not necessary to add the stuff wrapped in #if defined(_MSC_VER)
to boost itself. While it'd be a convenient implementation detail for
folks like me, just having mem_fn accept a traits class for member
function pointer types would simplify my life.

As an aside, #if defined(_MSC_VER) is probably not the way to check
for __stdcall anyway. Really, I should probably check to see if I'm
on the Windows platform, as I can't see how a compiler could work on
Windows without supporting those calling conventions and keywords,
since __stdcall is used throughout the Windows headers.
-steve anichini

Boost list run by bdawes at, gregod at, cpdaniel at, john at