Boost logo

Boost :

From: Paul Mensonides (pmenso57_at_[hidden])
Date: 2002-04-10 20:21:41


From: "David Abrahams" <david.abrahams_at_[hidden]>
> I understand, now. Thanks!
>
> It's not bad, but I don't yet see how to get it to deal with another
> level of iteration. Repeat 'N' of my macro typically contains a
> construct like:
>
> <class T1, class T2, ... class T(N-1)>
>
> You can't just create make1.h, make2.h,... can you?

That would require something a lot less intuitive at the point of definition,
yes. I'm just talking about the first level where you basically only have one
macro to expand.

I am (for obvious reasons) more used to my own library that does the same type
of stuff, so I'll give you an example from that. This is a generalized closure
to return from operator->* and it is intended to be used for smart_ptr types of
classes. Please note the use of at least 5 different recursive primitives. In
order to use an iterative mechanism, they entire thing would have to be
implemented much differently and a lot less straight forward. You could
eliminate the recursion altogether, but it would be a pain. :) In order to do
that, I think you would have to have a macro that expands to a filename instead
of a macro that takes a number--at least that is the incoherent jumble that is
going on in my head right now. :) Also, you would have to implement whatever
your expanding as a separate file with free-standing macros in the place of
arguments, since macros cannot expand to include directives. Anyway, enough
rambling. :) It is easy enough to take off the top level of recursion though,
and anything helps--plus you get separate lines which makes debugging *way*
easier.

// implementation of closure if you're interested
// in any case, this could be easily ported to use BOOST_PP instead

legend:

INSERT_PUNC: produces a comma (in this case) if C != 0
LIST_CLASS_T: class T1, class T2, ... class T(C)
LIST_T: T1, T2, T3, ... T(C)
LIST_PARAMS: T1 p1, T2 p2, T3 p3, ... T(C) p(C)
LIST_PARAM_IDS: p1, p2, p3, .. p(C)
ALPHA is a rogue parameter used for cv-qualified member functions.

// [closure.h]

// non-implemented

template<class> struct closure;

// implementation for pointers-to-data-members:
// the 'make' function just returns a reference
// to the data member

template<class T, class U> struct closure<U T::*> {
    typedef U& return_type;
    static inline U& make(T* obj, U T::* ptr) {
        return obj->*ptr;
    }
};

// turn *on* the preprocessor facilities...
??=include ENABLE(linearize.h)

// specialization macro for member functions:
// a specialization is created for a pointer-to-member function
// taking 0 to UPPER_BOUND parameters
// the class stores an object pointer and the pointer-to-member
// that it is constructed with and implements an operator() to actually
// call through the pointer to member.
// It also defines a 'make' function that returns a closure object.

#define MACRO(C) \
template<class R, class T INSERT_PUNC(C, COMMA) LIST_CLASS_T(C)> \
struct closure<R (T::*)(LIST_T(C)) ALPHA> { \
    private: \
        T* m_obj; \
        typedef R (T::* ptm_t)(LIST_T(C)) ALPHA; \
        ptm_t m_ptr; \
    public: \
        typedef closure return_type; \
        inline closure(T* obj, ptm_t ptr) : m_obj(obj), m_ptr(ptr) { \
            return; \
        } \
        inline R operator()(LIST_PARAMS(C)) const { \
            return (m_obj->*m_ptr)(LIST_PARAM_IDS(C)); \
        } \
        static inline closure make(T* obj, ptm_t ptr) { \
            return closure(obj, ptr); \
        } \
};

#define LOWER_BOUND 0
#define UPPER_BOUND 50

// generate the specializations
// note: this is done 4 times, one for each
// possible cv-qualification on a member function

#define ALPHA // no cv-qualification
#include "make.h"
#undef ALPHA

#define ALPHA const
#include "make.h"
#undef ALPHA

#define ALPHA volatile
#include "make.h"
#undef ALPHA

#define ALPHA const volatile
#include "make.h"
#undef ALPHA

// turn *off* the preprocessor facilities
??=include DISABLE(linearize.h)

// make_closure (a helper function)
// this function abstracts the difference between
// a constructor (of a function closure) and the
// implementation of a data closure.

template<class T, class ptr_mem_t>
inline typename closure<ptr_mem_t>::return_type
    make_closure(T* obj, ptr_mem_t ptr) {
        return closure<ptr_mem_t>::make(obj, ptr);
}

// -----

This implements a simple closure to return from operator->* for smart_ptr
classes. It works for pointers-to-data-members as well as
pointers-to-member-functions (including cv-qualifications). It can be used like
this:

template<class T> class smart_ptr {
    private:
        T* m_ptr;
        // ...
    public:
        // ...
        template<class U>
        inline typename closure<U>::return_type operator->*(U ptr) {
            return make_closure(m_obj, ptr);
        }
};

class X {
    void f(int x, int y) { }
};

int main() {
    smart_ptr<X> px = new X;
    void (X::* pf)(int, int);
    (px->*pf)(2, 3);
    return;
}


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk