19

Hallo,

is there some easy way in C++ to tell (in compile-time) if a class/struct has no data members?

E.g. struct T{};

My first thought was to compare sizeof(T)==0, but this always seems to be at least 1.

The obvious answer would be to just look at the code, but I would like to switch on this.

Johan Kotlinski
  • 25,185
  • 9
  • 78
  • 101

4 Answers4

20

Since C++11, you can use the std::is_empty trait.

If you are on paleo-compiler diet, you can use the Boost.TypeTraits implementation of is_empty. It relies on empty base optimisation, which is performed by all mainstream C++ Compilers, and ensures that an empty base class will take up zero space in a derived class.

The Boost.TypeTraits implementation uses a helper class which is derived from the class the user wants to test, and which is of a fixed, known size. A rough outline of the logic is as follows:

template <typename T>
struct is_empty {
    struct helper : T { int x; };
    static bool const VALUE = sizeof(helper) == sizeof(int);
};

However, beware that the actual Boost implementation is more complex since it needs to account for virtual functions (all mainstream C++ compilers implement classes with virtual functions by adding an invisible data member for the virtual function table to the class). The above is therefore not sufficient to implement is_empty correctly!

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • 2
    Will not work. As CashCow says this will not work for classes with virtual function. – UmmaGumma Jan 28 '11 at 14:06
  • 6
    @Ashot: That should not be "will not work" so much as "will not work given some definitions of empty". – GManNickG Jan 28 '11 at 14:12
  • @Ashot Martirosyan ... but the solution can be modified by deriving from some base helper class with dummy virtual function as welll as from the class being tested – user396672 Jan 28 '11 at 14:15
  • @GMan question is "has no data members". So answer is not clear. Your one are more clear IMHO :) – UmmaGumma Jan 28 '11 at 14:16
  • 1
    Ok, I should have made this clear: **don’t** use this metafunction, it’s for illustration purpose only. Use the Boost implementation, it’s much more robust and sophisticated! – Konrad Rudolph Jan 28 '11 at 14:16
  • 1
    This does work in the sense that it returns true for each empty class. However, if the result is false, the struct may or may not be empty, so "not `is_empty`" does not mean "is not empty". – Philipp Jan 28 '11 at 14:31
  • 1
    To @Konrad Rudolph. @user396672 is right, you can check is_polymorphic()&& sizeof(T)==sizeof(some_polymorphic_class). This will work for polymorphic classes on most compilers. It will not work only for classes with multiple inheritance (maybe also for classes with virtual bases). – UmmaGumma Jan 28 '11 at 14:46
  • 1
    Actually I like the **direct** instruction (i.e. not to use the example) from your comment enough to think it should be edited into the answer. – Spencer Mar 13 '23 at 15:22
  • @Spencer Agreed. Done. – Konrad Rudolph Mar 13 '23 at 15:34
12

If your compiler supports this aspect of C++0x, you can use std::is_empty from <type_traits>.

It's specification is:

T is a class type, but not a union type, with no non-static data members other than bit-fields of length 0, no virtual member functions, no virtual base classes, and no base class B for which is_empty<B>::value is false.

I don't think there's a standard way to find if a class is empty with regards to polymorphism.

GManNickG
  • 494,350
  • 52
  • 494
  • 543
  • how I already commented in Konrad Rudolph answer, it is possible to check if class is empty when it is polymorphic. You need to check `is_polymorphic()&& sizeof(T)==sizeof(some_polymorphic_class)`. This will work for polymorphic classes on most compilers. It will not work only for classes with multiple inheritance . – UmmaGumma Jan 28 '11 at 15:08
  • 4
    @Ashot: "on most compilers" I usually try not to think in terms of compilers. :) – GManNickG Jan 28 '11 at 15:14
3

Stepping on Konrad's answer, this handles classes with or without virtual functions.

template <typename T>
struct is_empty {
    struct empty_ { virtual ~empty_(); };
    struct helper_ : T { virtual ~helper_(); };
    static bool const EMPTY = sizeof(helper_) == sizeof(empty_);
};
Nick Dandoulakis
  • 42,588
  • 16
  • 104
  • 136
  • 1
    Ok, but the pointer to virtual table is not necessary sizeof(void*) (it seemes wrong, for instance, for 16-bit Borland C++ wich uses 2 bytes "short" pointer for this purpose regardless to memory model). It is better to compare with sizeof(SomeEmptyPolimorphicClass) – user396672 Jan 28 '11 at 15:14
-2

The most simple answer to this that both works and is standard complaint: Look at the header files for the class/struct and its class hierarchy. They will tell you if there are data elements (as well as a vtable).

Zac Howland
  • 15,777
  • 1
  • 26
  • 42