Boost logo

Boost :

From: Paul Mensonides (pmenso57_at_[hidden])
Date: 2002-11-10 04:19:33


----- Original Message -----
From: "Aleksey Gurtovoy" <agurtovoy_at_[hidden]>

> With the cleaned up "type deduction success/error?/failure garbage" :)

Here's a detector for operator(). It isn't perfect because you have to
specify the type of the function, but it's better than nothing:

#include <iostream>

template<class T> class has_function_call {
    private:
        template<class> struct extract;
        template<class R, class O> struct extract<R O::*> {
            typedef O type;
        };
        typedef char small_t;
        typedef char (& large_t)[256];
        template<T> struct helper;
        template<class U> static small_t check(helper<&U::operator()>*);
        template<class U> static large_t check(...);
    public:
        static const bool value =
            sizeof(check<typename extract<T>::type>(0)) == sizeof(small_t);
};

struct X {
    void operator()(void) {
        return;
    }
};

struct Y { };

struct Z {
    template<class T> T operator()(T v) const {
        return v;
    }
};

int main(void) {
    std::cout
        << has_function_call<void (X::*)(void)>::value << '\n'
        << has_function_call<void (Y::*)(void)>::value << '\n'
        << has_function_call<int (Z::*)(int) const>::value << '\n';
    return 0;
}

The interesting part is that it can also be used to detect arbitrary member
functions:

#include <iostream>

#define IMPLEMENT_OP(name, id) \
    template<class T> class name { \
        private: \
            template<class> struct extract; \
            template<class R, class O> struct extract<R O::*> { \
                typedef O type; \
            }; \
            typedef char small_t; \
            typedef char (& large_t)[256]; \
            template<T> struct helper; \
            template<class U> static small_t check(helper<&U::id>*); \
            template<class U> static large_t check(...); \
        public: \
            static const bool value = \
                sizeof(check<typename extract<T>::type>(0)) ==
sizeof(small_t); \
    }; \
    /**/

#define IMPLEMENT(id) IMPLEMENT_OP(has_ ## id, id)

IMPLEMENT(clone)
IMPLEMENT_OP(has_function_call, operator())

struct A {
    virtual A* clone(void) const {
        return new A(*this);
    }
    int operator()(void) {
        return 0;
    }
};

int main(void) {
    std::cout << has_clone<A* (A::*)(void) const>::value << &std::endl;
    std::cout << has_function_call<int (A::*)(void)>::value << &std::endl;
    return 0;
}

Of course, this will work on *very* few compilers. :(

Paul Mensonides


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