Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 567
Nyufu Avatar asked Sep 13 '17 10:09

Nyufu


People also ask

Can struct be used as base class for inheritance?

Yes, struct can inherit from class in C++. In C++, classes and struct are the same except for their default behaviour with regards to inheritance and access levels of members.

How do you check if an object belongs to a certain class in C++?

C++ has no direct method to check one object is an instance of some class type or not. In Java, we can get this kind of facility. In C++11, we can find one item called is_base_of<Base, T>. This will check if the given class is a base of the given object or not.

Is C++ a base class?

Difference between Base class and Derived class in C++ Base Class: A base class is a class in Object-Oriented Programming language, from which other classes are derived. The class which inherits the base class has all members of a base class as well as can also have some additional properties.

Is base a class?

What is a Base Class? In an object-oriented programming language, a base class is an existing class from which the other classes are determined and properties are inherited. It is also known as a superclass or parent class.


2 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.

like image 68
ecatmur Avatar answered Sep 24 '22 04:09

ecatmur


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:

  • std::is_pod

  • std::is_trivial

  • std::is_aggregate

like image 37
Vittorio Romeo Avatar answered Sep 21 '22 04:09

Vittorio Romeo