Если параметр шаблона AA сам является шаблонным классом A<T>, возможно ли получить параметр шаблона (T) этого шаблонного класса?

Рассмотрим код ниже:

template <typename T>
class A{
...
}

template <class U>
class B{
...
}

int main {
B<A<int>> a;
...
}

Как я могу получить параметр шаблона A (в данном случае int) внутри B, если A<int> является параметром шаблона для B? Я мог бы параметризовать B следующим образом, но мне кажется, что я отправляю ненужную часть информации.

template <class AA, typename T>
class B { ... }

Причина, по которой я не просто использую template <typename T> для класса B, заключается в том, что у меня есть указатель на класс A внутри B, и я хочу использовать параметр шаблона class AA, чтобы увидеть, является ли этот указатель константным или нет, следовательно, иметь правильный тип для члена указатель в Б.

Вы можете частично специализировать его, как template<typename T> class B<A<T>> { /* whatever */ };. И в вашем собственном решении тоже нет ничего плохого. Ваш вопрос слишком расплывчатый, чтобы дать более конкретный ответ.

Tanveer Badar 15.12.2020 15:42

@TanveerBadar, спасибо за ответ. класс B должен всегда иметь A<T> в качестве параметра шаблона. Именно T является реальным параметром (как и постоянство A<T>).

KMot 15.12.2020 15:51

Так почему бы не использовать template <typename T> class B{ A<T> X; ...}; ?

Damien 15.12.2020 16:04

@Damien, потому что у меня есть «A<T>* X» или «const A<T>* X» в зависимости от того, является ли A константой или нет. Предположим, что A — очень большой класс, и я хочу иметь указатель на него внутри B, но в то же время A может быть константным или нет. Я задал еще один вопрос по этому поводу здесь: stackoverflow.com/q/65286216/10755448

KMot 15.12.2020 16:11

Я не вижу, что это меняет. У вас может быть `template <typename T> class B{ A<T> *X; константа A<T> *Y; ...}; ...

Damien 15.12.2020 16:13

@ Дэмиен, возможно, я чего-то не знаю или не понимаю. Но позвольте мне уточнить. У меня есть только X, он указывает на A, что A может быть константой или нет, поэтому тип X зависит от константности A, на которую он указывает. Предположим, что B создан внутри A и внутри A.

KMot 15.12.2020 16:32
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
6
73
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Я думаю, что следующее делает то, что вы хотите:

#include<type_traits>
template<class>
class A{};

template<class>
struct get_inner;

template<template<class> class TT, class T>
struct get_inner<TT<T>> {
    using outer = TT<T>;
    using inner = T;
};

template<class TT>
struct B {
    using A = TT;
    using inner = typename get_inner<std::decay_t<A>>::inner;
};


int main(int argc, char *argv[])
{
    static_assert(std::is_const_v<typename B<const A<int>>::A>);
        static_assert(!std::is_const_v<typename B<A<int>>::A>);
}

Обратите внимание на std::decay_t, он не будет работать с параметром const напрямую (поэтому мы не можем просто специализировать B таким образом). Может быть, decay_t немного сильно, но это работает ^^

Попробуй это

template <typename X> class B;

template <template <typename> class XX, typename T>
class B<XX<T>>
{
    // your implementation
};

B<A<int>> a;
Ответ принят как подходящий

Есть несколько способов, в зависимости от которых вы можете изменить:

  • Быстрый путь, специализация B

    template <class> class B;
    
    template <class T>
    class B<A<T>>
    {
        // Use directly T
        //...
    };
    
  • Добавить информацию напрямую в A (как стандартные контейнеры делают с value_type)

    template <typename T>
    struct A
    {
        using my_type = T;
    };
    
    // Then in `B<U>`, use `typename U::my_type`
    
  • Используйте внешние признаки для извлечения информации из A (как std::iterator_traits) (что также позволяет обрабатывать встроенные типы):

    template <typename T>
    struct ATrait;
    
    template <typename T>
    struct ATrait<A<T>>
    {
        using my_type = T;
    };
    
    // Possibly a generic one
    template <template <typename> class C, typename T>
    struct ATrait<C<T>>
    {
        using my_type = T;
    };
    
    // Then in `B<U>`, use `typename ATrait<U>::my_type`
    

Другие вопросы по теме