0

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?

2
  • 1
    "...should use the same types as class A..." -- There is no class A. There is just a class template called A... Commented Jun 20, 2022 at 8:42
  • Should only A<T,U> instances be accepted as A_Types in B<A_Type> ? Commented Jun 20, 2022 at 12:03

3 Answers 3

2

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

Sign up to request clarification or add additional context in comments.

1 Comment

value_type should be protected at least.
1

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

5 Comments

Yeah this was my solution for now but it is not a very clean one imo. Because you always have to add the type twice (B<A<T, U>, T> instead of B<A<T, U>>)
@str0yd if it should be possible to instantiate some B<A<T,U>,V> with V!=T, this is actually the way to go, and for T==V an alias can be used template <typename T,typename U> using BA = B<A<T,U>,T>;
@str0yd: is the member j of class B at the right place ?
@YvesDaoust yea it is in the right place. In my concrete example class A has some position : T and the class B is a "range check" for this position, maxPos : T and minpos : T
@str0yd: why isn't this in the class A ?
0

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.