Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get nearest base class

Tags:

c++

I have a class hierarchy:

struct B {};
struct D1 : B {};
struct D2 : B {};

Is it possible using some sort of std:: helper functions/classes (likely from <type_traits>) get common base class (i.e. B) for two variables:

D1 d1;
D2 d2;

I had tried to use std::common_type_t<decltype(d1), decltype(d2)>, but no luck.

like image 841
αλεχολυτ Avatar asked Oct 26 '25 15:10

αλεχολυτ


1 Answers

http://www.cplusplus.com/reference/type_traits/common_type/

If you look at the code that implements common_type, it appears that it selects between the types that are inputted into the list. This is the reference behavior:

template <class... Types> struct common_type;

template <class T> struct common_type<T> {
  typedef T type;
};

template <class T, class U> struct common_type<T,U> {
  typedef decltype(true?declval<T>():declval<U>()) type;
};

template <class T, class U, class... V> struct common_type<T,U,V...> {
  typedef typename common_type<typename common_type<T,U>::type,V...>::type     type;
};

So if you only input one type "T", then it returns a typedef of that type. If you input two types, the "magic" happens in this line:

true?declval<T>():declval<U>()

What this does is it uses a ternary instruction (X?Y:Z) with an always-true argument to pick between two possible outcomes. Since a ternary can only have one return type, then the normal conversion rules of C++ apply: the standard conversion rules are applied to ensure this instruction has only one return type. That is the "trick" here. That process fails when you plug a D1 and a D2 into it, because the ternary instruction doesn't know what to turn both a D1 and a D2 into. So common_type relies on already-existing conversion logic inside C++ and can't actually find class "B".

You can in fact check B against D1, or B against D2, or B / D1 / D2 all at the same time (it uses template recursion to solve three or more), and each of these common_type calls will correctly tell you that B is the common type, but without including B in the check, the code implementation cannot return B for you.

If you want what you're asking for you probably need to build it specifically for the class heirarchy that you're after.

like image 56
Jason Lang Avatar answered Oct 29 '25 06:10

Jason Lang



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!