With C++17 is it possible to detect if a struct/class has any base?

I need a type trait which will be true if the given type derives from anything, and false otherwise.

For example:

template<class T>
struct is_inherit
    //... logic of inheritance detection
    ;

template<class T>
void AppLogic(){
    if constexpr(is_inherit<T>::value) {
        puts("T has base");
        //...
    } else {
        puts("T doesn't have base");
        //...
    }
}

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

int main() {
    AppLogic<A>(); // print: T doesn't have base 
    AppLogic<B>(); // print: T has base
}

Is it possible to somehow implement that "is_inherit" trait struct?


Why?

I am developing a manual stack frame builder for Windows x64. According the https://docs.microsoft.com/en-us/cpp/build/return-values-cpp documentation, if a type:

  • has a length of 1, 2, 4, 8, 16, 32, or 64 bits;
  • has no user-defined constructor, destructor, or copy assignment operator;
  • has no private or protected non-static data members;
  • has no non-static data members of reference type;
  • has no base classes;
  • has no virtual functions;
  • and has no data members that do not also meet these requirements;

then its return value is in the RAX register, otherwise the function has a hidden argument that I must detect and handle.

This used to be the definition of a C++03 POD, however in C++11 this changed:

Because the definition has changed in the C++11 standard, we do not recommend using std::is_pod for this test.

Up until now, with some conjugated traits I could detect if the type met the definition of a C++03 POD or not. However with C++17 the aggregate rules have changed, and that broke my solution.

If I can somehow detect whether a type T has any base class, my solution will work again.

Answers


Yes, this is possible, at least for aggregates.

First we construct a class template that is convertible to any proper base of its template parameter:

template<class T>
struct any_base {
    operator T() = delete;
    template<class U, class = std::enable_if_t<std::is_base_of_v<U, T>>> operator U();
};

Then we detect whether a template parameter T is aggregate constructible from a value of type any_base<T>:

template<class, class = void> struct has_any_base : std::false_type {};
template<class T>
struct has_any_base<T, std::void_t<decltype(T{any_base<T>{}})>> : std::true_type {};

Example.


I believe that checking if "T derives from anything" is not possible, at least not in a standard-compliant way. If you are using this technique to check whether or not a type is a POD/trivial/aggregate, there are some type traits that might help you:


Need Your Help

How do I redirect a user when a button is clicked?

asp.net-mvc

I have a view with a button. When the user clicks the button I want them redirected to a data entry view. How do I accomplish this? I should mention the views are created, tested, and functioning. ...