Consider the code below:

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

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

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

How can I get the template parameter of A (int in this case) inside B, if A<int> is the template parameter for B? I could parametrize B as follows, but I feel like I am sending an unnecessary piece of information.

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

The reason I do not simply use template <typename T> for class B is that I have a pointer to class A inside B, and I want to use the template parameter class AA to see if that pointer is const or not, hence have the correct type for the member pointer in B.

3

There are 3 answers

0
Jarod42 On BEST ANSWER

There are several ways, depending of that you might change:

  • Quick way, specialize B

    template <class> class B;
    
    template <class T>
    class B<A<T>>
    {
        // Use directly T
        //...
    };
    
  • Add info in A directly (as std containers do with value_type)

    template <typename T>
    struct A
    {
        using my_type = T;
    };
    
    // Then in `B<U>`, use `typename U::my_type`
    
  • Use external traits to extract information from A (as std::iterator_traits) (that also allows to handle built-in types):

    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`
    
0
n314159 On

I think the following does what you want:

#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>);
}

Note the std::decay_t, it wouldn't work with the const parameter directly (hence we cannot just specialize B in this way). Maybe decay_t is a bit strong but it works^^

0
n. m. could be an AI On

Try this

template <typename X> class B;

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

B<A<int>> a;