c++ - шаблонов - с++ шаблоны




Получить самый внутренний тип шаблона внутри самого шаблона (4)

возможно ли извлечь изнутри шаблон сокрытых шаблонов одного типа из одного типа? Я хотел бы получить double тип в следующем примере:

template<typename T>
struct is_a : std::false_type {};

template<typename T>
struct A
{
    using type = std::conditional_t<
        is_a<T>::value,
        T::type, // if it's an A, go deeper
        T>;      // if not, we're done
};
template<typename T>
struct is_a<A<T>> : std::true_type {};

int main()
{
    A<A<A<A<A<double>>>>>::type d = 3.0;
    return 0;
}

Это было мотивировано этим question . Кроме того, я нашел этот post , указав, что он может что-то делать с использованием ключевого слова typename или template , но я не мог заставить его работать сам.


Альтернатива ответу Марко (правильный). Вы можете поместить некоторые из этих логик выбора типа в класс признаков:

// step 1 - predeclare the template A

template<typename T> struct A;

// define a default specialisation of a traits type
template<class T> struct ATraits
{
    using type = T;
};

// specialise the traits for the A<T> case
template<class T> struct ATraits<A<T>>
{
    using type = typename A<T>::type;
};

// now define the A template default specialisation
template<typename T>
struct A
{
    using type = typename ATraits<T>::type;
};

int main()
{
    A<A<A<A<A<double>>>>>::type d = 3.0;
    return 0;
}

Вы можете использовать enable_if и SFINAE для выбора самого сокровенного типа:

template<typename T, class Enable = void>
struct A {
    using type = T;
};

template<typename T>
struct A<T, std::enable_if_t<!std::is_same_v<T, typename T::type>>> {
   using type = typename T::type;
};

Обычный трюк, чтобы сделать это с вашим первоначальным подходом, - это отложить оценку:

template<class T> struct type_identity { using type = T; };

template<typename T>
struct A
{
    using type = typename std::conditional_t<
        is_a<T>::value,
        T,
        type_identity<T>>::type;
};

Помимо вашей опечатки отсутствующего имени, проблема здесь:

using type = std::conditional_t<
    is_a<T>::value,
    T::type, // if it's an A, go deeper
    T>;      // if not, we're done

что std::conditional не является короткозамкнутым. Если T не имеет члена type , это приведет к ошибке.

Вы можете написать мета-функцию для рекурсивного извлечения внутреннего типа:

template<class T>
struct extract_type {
    using type = T;
};

template<class T> class A;

template<class T>
struct extract_type<A<T>> {
    using type = typename extract_type<T>::type;
};

template<typename T>
struct A
{
    using type = typename extract_type<T>::type;
};

int main()
{
    A<A<A<A<A<double>>>>>::type d = 3.0;
    return 0;
}




types