Boost logo

Boost :

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


I posted this at comp.std.c++, but I don't think it went through--I'm not trying
to 'cross-post'. :)

I'm curious about the legality of the following construct. It is attempting to
test whether a give type 'T' has a member function 'self'.

template<class T> struct has_self {
    private:
        typedef char small_t;
        typedef char (& large_t)[256];
        template<class U> struct helper {
            template<void (U::*)(void)> struct inner { };
        };
        template<class U> static small_t check( typename helper<U>::template
inner<&U::self>* );
        template<class U> static large_t check( ... );
    public:
        static const bool value = sizeof(check<T>(0)) == sizeof(small_t);
};

struct X { }; // no 'self'

struct Y {
    void self(void) {
        return;
    }
};

int main() {
    std::cout
        << has_self<X>::value << '\n'
        << has_self<Y>::value << &std::endl;
    return 0;
}

This compiles and words as desired on Comeau C++, but I'm wondering if it is
*legal* C++. I'm using it to create an unbounded (theoretically) multi-method
dispatcher, but I need to check where a type has that member function. If not,
then I need to revert (at compile-time) to using dynamic_cast.

By the way, I already have it working as long as the object has the following
definition:

struct some_type {
    virtual void self(void) {
        throw this;
    }
};

For a double dispatch:

struct X {
    virtual void self(void) {
        throw this;
    }
};

struct Y : X {
    void self(void) {
        throw this;
    }
};

struct handler {
    typedef const char* return_type;
    inline return_type operator()(X& a, X& b) {
        return "default used";
    }
    inline return_type operator()(Y& a, Y& b) {
        return "Y Y found";
    }
};

int main() {

    typedef TYPELIST(( X, Y )) types;
    MULTI_METHOD(( types, types )) multi;

    X x;
    Y y;

    X& rx = x;
    X& ry = y;

    std::cout << multi( rx, ry, handler() ) << '\n';
    std::cout << multi( ry, ry, handler() ) << &std::endl;

    return 0;
}

With __VA_ARGS__ from C99, I could reduce it to:

MULTI_METHOD(TYPELIST(X, Y), TYPELIST(X, Y)) multi;

The main problem is that the necessity of 'self' is intrusive, so I want to
detect if it exists and if not use a dynamic_cast implementation instead.

Paul Mensonides

(P.S. note to Andrei Alexandrescu...)

Andrei, I haven't tested the performance characteristics when compared to Loki's
multi-methods, but it seems to work fairly quickly. With a good exception
handling mechanism it can be even better.


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