0

I want to detect during compile time (static assertion) whether a class meets both the following conditions:

  • Has an implicit default constructor (i.e., no user-defined default constructor).
  • Has at least one data member which is a pod (i.e., a member whose default initialization is to assume whatever random bytes was in its memory address). [I hope I used the term pod correctly here]

The idea is to avoid working with objects with uninitialized members. I know there are different methods to do this during coding, but I also want a mechanism to detect this during compilation. I tried using different std/boost functions, such as is_trivially_constructible, is_pod, but none of these provide the exact terms I need.

For example, let's say I have the following classes:

struct A
{
  int a;
}

struct B
{
  int* b;
}

struct C
{
  bool c;
  std::string c_str_; 
}

struct D
{
  D();
  float d; 
}

struct E
{
  std::string e;
}

Assuming the function I need is called "has_primitive_and_implicit_ctor", I would like the output for each call to be as in the comments:

has_primitive_and_implicit_ctor<A>(); //true - A has at least one pod type member (int)
has_primitive_and_implicit_ctor<B>(); //true - A has at least one pod type member (pointer)
has_primitive_and_implicit_ctor<C>(); //true - A has at least one pod type member (bool), even though there is one non-pod member
has_primitive_and_implicit_ctor<D>(); //false - has a pod member(float), but a user defined ctor
has_primitive_and_implicit_ctor<E>(); //false - doesn't have a default ctor but has no pod members
  • You cannot detect type members automatically (i.e. you cannot iterate over the members of a type). Also you can use aggregate initialization to fully initialize types that contain uninitialized pods. – Timo Jun 26 '19 at 14:19
  • You probably want to do it with static analyser, clang tooling might help. – Jarod42 Jun 26 '19 at 14:36
  • @MaximEgorushkin just from a typename? Now I'm curious. – Timo Jun 26 '19 at 14:40
  • 1
    @Timo It is possible to iterate over members of a class that supports aggregate initialization with https://github.com/apolukhin/magic_get . Unfortunately, it chokes on `std::string` members. Otherwise it would be almost trivial to iterate over all members and tell whether any is POD. – Maxim Egorushkin Jun 26 '19 at 15:25
  • @MaximEgorushkin wow that is genius. I get the idea behind it but I don't understand how the member counting works. And how can an aggregate initialization be performed (in order to receive the member types) without having to explicitly write it out for each possible member count (like `T{m1, m2, m3}`, `mX` beeing the detectors)? – Timo Jun 26 '19 at 17:19
  • 1
    @Timo See the author's talk with full details: [Better C++14 reflections - Antony Polukhin - Meeting C++ 2018](https://youtu.be/UlNUNxLtBI0). – Maxim Egorushkin Jun 26 '19 at 17:21

1 Answers1

2

Firstly, it seems to me like a broken design to expect from the user of a class to care about its member initialisation. You should make sure in the class itself that all its members are initialised, not somewhere else where it is used.

What you are looking for does not exist, and if it would, it would not even help you. The existence of an explicit constructor does not guarantee that a data member is initialised. On the other hand, with C++11 it is even possible to initialise data members without explicitly writing a constructor (using the brace syntax in the class declaration). Also you just seem to care about uninitialised POD members, but what about uninitialised non-POD members?

That said, compiler can generate warnings about uninitialised values, but often you have to enable this warning (e.g. -Wuninitialized option for gcc). Most compilers allow to force treating warnings as an error. In combination this can give you the desired effect even without specifically writing code to test for it, and it would also work for any uninitialised values, not only those in classes. Maybe this is the solution you are looking for.

  • 1
    `-Wuninitialized` is included in `-Wall`. One should always start with `-Wall -Wextra -Werror`. +1 – Maxim Egorushkin Jun 27 '19 at 09:22
  • Using -Wuninitialized, I don't get warnings for classes without a constructor that have POD members, and don't get warnings for constructors which don't initialize some of their POD members. Also, the IDE I'm working with (eclipse) has warnings about constructors that don't init POD members, but doesn't have warnings about classes without constructors. Any ideas? – Eran Bentov Jun 30 '19 at 07:52
  • @EranBentov gcc 5.4.0 gives me warnings for uninitialised POD members of classes. Note that it gives that warning when the member is used, not when the constructor does not initialise it. There is no requirement that the constructor should initialise all its members. Which compiler and version are you using? – Martin Hierholzer Jul 01 '19 at 08:14
  • I'm using gcc 4.8.5 – Eran Bentov Jul 03 '19 at 11:34
  • @EranBentov that is pretty old, from 2015. I would recommend using a newer gcc. Even my 5.4.0 is very old, but I am kinda stuck with it for now unfortunately. The most recent version is gcc 9.1. There have been many improvements in the warning and error messages, many things get much easier! – Martin Hierholzer Jul 04 '19 at 12:06