Получить самый внутренний тип шаблона в самом шаблоне - PullRequest
0 голосов
/ 15 мая 2018

возможно ли извлечь самый внутренний тип суммированных шаблонов того же типа из шаблона ? Я хотел бы получить тип 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;
}

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

Ответы [ 5 ]

0 голосов
/ 15 мая 2018

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

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;
};
0 голосов
/ 15 мая 2018

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

// 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;
}
0 голосов
/ 15 мая 2018

Если я что-то упустил, я бы частично специализировал шаблон, чтобы упростить процесс

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

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

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

Живой образец

0 голосов
/ 15 мая 2018

Вы можете использовать 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;
};
0 голосов
/ 15 мая 2018

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

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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...