Тип решения, основанный на существовании вложенного typedef - PullRequest
7 голосов
/ 20 октября 2010

Мне нужно определить структуру шаблона так, чтобы:

element<T>::type

имеет тип:

T::element_type 

если T содержит (public) typedef с именем element_type, в противном случае (если он не содержит такой typedef)

element<T>::type

имеет тип

T::value_type 

если T изменчив и имеет тип

const T::value_type

если Т постоянна.

Я действительно борюсь с этим, любое предложение очень ценится! :)

Большое спасибо за вашу помощь заранее!

Ответы [ 2 ]

4 голосов
/ 20 октября 2010

Может быть что-то вроде:

template <typename T>
struct has_element_type
{
    typedef char yes[1];
    typedef char no[2];

    template <typename C>
    static yes& test(typename C::element_type*);

    template <typename>
    static no& test(...);

    static const bool value = sizeof(test<T>(0)) == sizeof(yes);
};

template <typename T>
struct is_const
{
    static const bool value = false;
};


template <typename T>
struct is_const<const T>
{
    static const bool value = true;
};

template <typename, bool> // true -> const
struct value_type_switch; 

template <typename T>
struct value_type_switch<T, true>
{
    typedef const typename T::value_type type;
};

template <typename T>
struct value_type_switch<T, false>
{
    typedef typename T::value_type type;
};

template <typename, bool> // true -> has element_type
struct element_type_switch;

template <typename T>
struct element_type_switch<T, true>
{
    typedef typename T::element_type type;
};


template <typename T>
struct element_type_switch<T, false>
{
    typedef typename value_type_switch<T, is_const<T>::value>::type type;
};

template <typename T>
struct element
{
    typedef typename element_type_switch<T,
                                    has_element_type<T>::value>::type type;
};

Это, конечно, должно быть разделено и организовано.

1 голос
/ 20 октября 2010

В качестве альтернативы объявлению класса признаков с помощью SFINAE вы можете использовать его более тонко с частичной специализацией.

template< typename T >
struct empty { // support class is like stripped-down enable_if
    typedef void type;
};

template< class T, typename v = void > // v is always void!
struct element {
    typedef typename T::value_type type;
};

template< class T, typename v >
struct element< T const, v > {
    typedef typename T::value_type const type;
};

template< class T > // T in deduced context, T::element_type is SFINAE:
struct element< T, typename empty< typename T::element_type >::type > {
    typedef typename T::element_type type;
};

… вы можете добавить еще один случай, чтобы сделать element_type const для const T?К сожалению, это не работает в GCC, хотя Comeau принимает его.

template< class T >
struct element< T const, typename empty< typename T::element_type >::type > {
    typedef typename T::element_type const type;
};

Код, который я использовал для проверки этого:

struct has_et {
    typedef int element_type;
};

struct has_vt {
    typedef char value_type;
};

char c;
int i;

element<has_vt>::type *cp = &c;
element<has_et>::type *ip = &i;
...