5

Yesterday faced with problem how to get all base classes from some class. For example:

class Object 
{
public:
   Object() = default;
};

class DerivedOne
   : public Object
{
public:
   DerivedOne() = default;
};

class DerivedTwo
   : public Object
   , public DerivedOne
{
public:
   DerivedTwo() = default;
};

I want to get all base class for DerivedTwo in typelist => { Object, DerivedOne, Object} It is needed for deny inheritance from Object class more than one time.

Has somebody such expirience or knowledge how to do it ?

Denis Kotov
  • 857
  • 2
  • 10
  • 29
  • C++ doesn't have reflection yet. You could use the branch of Clang that has a reflection proposal implemented, though. – chris Mar 25 '17 at 18:22
  • The abandoned TR2 had such a trait, and I think GCC implements it. But of course that's not portable. – Kerrek SB Mar 25 '17 at 18:25
  • @chris Maybe some boost library can do it ? – Denis Kotov Mar 25 '17 at 19:01
  • @ Kerrek SB: What do you think maybe some boost library can do it ? – Denis Kotov Mar 25 '17 at 19:02
  • Arbitrary base classes? Or are you allowed to enforce some sort of convention for all base classes? – lapk Mar 25 '17 at 19:05
  • @DenisKotov, No, it requires compiler help. The closest you can come would require feeding the library the base classes in some way. – chris Mar 25 '17 at 19:09
  • At run time you want this list ? – Vishal Gupta Mar 29 '17 at 06:59
  • @ Vishal Gupta: Of course at **compile time** – Denis Kotov Mar 29 '17 at 20:36
  • Maybe you should be able to achieve something with recursive CRTP and let the Base class hold the typelist (flatten a tuple of tuple of...). But that's ugly. – Mathieu Van Nevel Mar 31 '17 at 13:48
  • @MathieuVanNevel if you're still around, could you please provide an example on how to achieve that? – Fureeish Aug 06 '18 at 23:50
  • @Fureeish well the problem is that the OP code is invalid (ambiguity) , so just modifying it will give me the same error. And I'd like to know for what use he wanted this, to do somethiung a bit correct. – Mathieu Van Nevel Aug 13 '18 at 14:48
  • @MathieuVanNevel I encountered this question because I was looking for a solution (since C++ doesn't offer reflection) for my own problem. Imagine a `template struct foo` and then a `struct bar` that will inherit for example from `foo<16>, foo<64>, foo<32>`. I wanted to somehow get the *biggest* value of `foo`s template value. Any idea how to? The problem of multiple inheritance is the issue here. I kinda want to *iterate over base classes' template values*, but I doubt it's possible. It's easy to access the single value, but I have no idea how to compare an arbitrary number of them – Fureeish Aug 13 '18 at 16:26
  • 1
    @Fureeish Sorry I forgot... There is the basic idea, but obviously it need to be adapted to your needs : https://wandbox.org/permlink/MGo9oCmgZGx1Mfvk Btw, next time open another question :) – Mathieu Van Nevel Aug 16 '18 at 13:19

1 Answers1

0

The comments mention TR2 reflection proposal which is "abandoned" but yet has an implementation in gcc. The code below is based on SO post: Finding base class at compile time

Preparing a tuple to hold the types returned from TR2

#include<tr2/type_traits>

template<typename T>
struct types_as_tuple;

template<typename... Ts>
struct types_as_tuple<std::tr2::__reflection_typelist<Ts...>>
{
    typedef std::tuple<Ts...> type;
};

Checking for duplicate type in a tuple

template<typename T>
struct duplicate_type;

template<typename T1, typename T2, typename... Ts>
struct duplicate_type<std::tuple<T1, T2, Ts...>> {
    constexpr static bool value = std::is_same<T1, T2>::value
                                  || duplicate_type<std::tuple<T1, Ts...>>::value;
                                  || duplicate_type<std::tuple<T2, Ts...>>::value 
};

template<typename T1, typename T2>
struct duplicate_type<std::tuple<T1, T2>> {
    constexpr static bool value = std::is_same<T1, T2>::value;
};

TypesPrinter

template<typename T>
struct TypesPrinter;

template<typename T>
struct TypesPrinter<std::tuple<T>> {
    constexpr TypesPrinter() {
        std::cout << typeid(T).name() << ' ';
    }
};

template<typename T, typename... Ts>
struct TypesPrinter<std::tuple<T, Ts...>> {
    constexpr TypesPrinter() {
        TypesPrinter<std::tuple<T>>();
        TypesPrinter<std::tuple<Ts...>>();
    }
};

Main

struct A {};
struct B: A {};
struct C {};
struct D : B, C, A {};

int main() {
    //---------------------------------------------------------------
    // getting all direct and indirect bases of a class with TR2
    //---------------------------------------------------------------
    using bases_of_D = types_as_tuple<std::tr2::bases<D>::type>::type;

    //---------------------------------------------------------------
    // checking for duplication at compile time
    // (can also use static_assert)
    //---------------------------------------------------------------
    if constexpr(duplicate_type<bases_of_D>::value) {
        std::cout << "duplicate base in class D" << std::endl;
    }

    //---------------------------------------------------------------
    // printing the types
    //---------------------------------------------------------------
    TypesPrinter<bases_of_D>();

}

http://coliru.stacked-crooked.com/a/d556c47c660832ff

Amir Kirsh
  • 12,564
  • 41
  • 74