Home > Software design >  Template class arguments as type
Template class arguments as type

Time:06-20

I have a class

template<typename T, typename U>
class A {
  T i;
}

And i have a class B that should use the same types as class A

template<typename A_Type>
class B
    : public A_Type
{
  T j; // here I need a class member of the same type as the first type of A_Type (T from class A)
}

So I would need something like

template<typename A_Type<T, U>>
class B
    : public A_Type
{
  T j; 
}

This notation is obviously not working but is there a notation that would fit my needs?

CodePudding user response:

You can provide a member alias in A :

template<typename T, typename U>
class A {
  T i;
  using value_type = T;
};

template<typename A_Type>
class B
    : public A_Type
{
  typename A_Type::value_type;
};

Or use specialization to deduce the type of the argument:

template<typename T, typename U>
class A {
  T i;
  using value_type = T;
};

template<typename A_Type>
class B : public A_Type {};

template <typename T,typename U>
class B<A<T,U>> : A<T,U> {
    T j;
};

As mentioned in comments, try to be careful with terminology. Using the terms right avoids issues. Neither A nor B are classes. They are class templates. And the member alias should be protected (or placed in a seperate trait template <typename A> struct get_T_from_instantiation_of_A;)

CodePudding user response:

Can't you just pass that type ?

template<typename A_Type, typename T>
class B
    : public A_Type
{
  T j; // here I need a class member of the same type as the first type of A_Type (T from class A)
}

CodePudding user response:

You could create some type traits to help out.

First one to test if a type is really an A type:

#include <type_traits>

template<class T>
struct is_A_type {
    static std::false_type test(...);
    
    template<template<class...> class U, class... V,
                      std::enable_if_t<std::is_same_v<U<V...>, A<V...>>, int> = 0>
    static std::true_type test(const U<V...>&);

    static constexpr bool value = decltype(test(std::declval<T>()))::value;
};

template<class T>
inline constexpr bool is_A_type_v = is_A_type<T>::value;

Then a trait to get the type of the first template parameter:

template<class T>
struct first_type {
    static void test(...);

    template<template<class...> class U, class F, class... V>
    static auto test(const U<F, V...>&) -> F;

    using type = decltype(test(std::declval<T>()));
};

template<class T>
using first_type_t = typename first_type<T>::type;

These traits could then be used like so:

template<class A_Type>
class B : public A_Type {
    static_assert(is_A_type_v<A_Type>, "A_Type must be an A type");

    using T = first_type_t<A_Type>;
    
    T j;
};
  • Related