From: Paul Mensonides (pmenso57_at_[hidden])
Date: 2002-04-25 21:07:35


BTW, this is how I 'solved' the 'has_key_type' and 'has_template_type' on Comeau
C++ (beware, this is ugly!):
--------------------------------------------------
template<class> char binding(void);

template<template<class> class>
    char (& binding(void))[2];

template<template<class, class> class>
    char (& binding(void))[3];

// etc.

typedef char small_t;
typedef char (& large_t)[256];

template<bool, class A, class B> struct select {
    typedef B type;
};

template<class A, class B> struct select<true, A, B> {
    typedef A type;
};

template<int> struct scope;

template<> struct scope<1> {
    template<template<class> class T>
    struct helper {
        typedef typename
            select<
                sizeof(binding<T>()) - 1U == 1U,
                int,
                void
>::type type;
    };
};

template<> struct scope<2> {
    template<template<class, class> class T>
    struct helper {
        typedef typename
            select<
                sizeof(binding<T>()) - 1U == 2U,
                int,
                void
>::type type;
    };
};

template<> struct scope<3> {
    template<template<class, class, class> class T>
    struct helper {
        typedef typename
            select<
                sizeof(binding<T>()) - 1U == 3U,
                int,
                void
>::type type;
    };
};

// etc.

template<class T> class has_template_type {
    private:
        #define GEN(i) \
            template<class U> static small_t check( \
                typename scope<i>::helper<U::template type>::type (*)[1] \
            );
        GEN(1)
        GEN(2)
        GEN(3)
        // etc.
        #undef GEN
        template<class U> static large_t check(...);
    public:
        static const bool value = sizeof(check<T>(0)) == sizeof(small_t);
};

template<class T> const bool has_template_type<T>::value;

template<class T, bool = has_template_type<T>::value> class has_key_type;

template<class T> class has_key_type<T, false> {
    private:
        template<class U> static small_t check( typename U::type* );
        template<class U> static large_t check( ... );
    public:
        static const bool value = sizeof(check<T>(0)) == sizeof(small_t);
};

template<class T> const bool has_key_type<T, false>::value;

template<class T> class has_key_type<T, true> {
    public:
        static const bool value = false;
};

template<class T> const bool has_key_type<T, true>::value;

struct X { };

struct Y {
    struct type { };
};

struct Z {
    template<class> struct type { };
};

#include <iostream>
#include <typeinfo>

template<class T> void test() {
    std::cout
        << typeid(T).name() << " : "
        << has_key_type<T>::value << ' '
        << has_template_type<T>::value << &std::endl;
    return;
}

int main() {
    test<X>();
    test<Y>();
    test<Z>();
    return 0;
}
--------------------------------------------------
This program outputs:

X : 0 0
Y : 1 0
Z : 0 1

Phew! By the way, if I remove the 'select' test from 'scope', I get errors.
This way, it causes it to fail type deduction in another way (I guess.).

Paul Mensonides