Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

empty brace-init-lists emit warnings about missing field initializers

Tags:

c++

c++11

Goal: to be able list-initialize objects and to have the default initialization init all PODs to 0/false with as little boilerplate as possible (C++11).

Assume I have several classes with several PODs (think of file format parsing). In order not to deal with undefined values I would like the default constructed objects to be value-initialized to 0. For example, providing my own default c'tor that memset()s this works fine for such cases, as does naming all members explicitely.

However, this is boilerplate. Even more importantly providing my own argument-less default constructor prevents me from using the list initializer syntax for member initialization:

class Fails1 {
public:
  int a, b;
  Fails1() { memset(this, 0, sizeof(*this)); }
};

Fails1 this_works;
Fails1 this_fails{ 42, 54 }; // compiler error

I could add the constructor for the initializer_list as well, but that's even more boilerplate. I want to avoid all that boilerplate.

So I looked at the default constructors provided by the compiler when there's no user-provided default constructor in combination with the various methods how one can initialize them. Here's where I got totally confused:

class A {
public:
  int a, b;
};

With this class I can use both empty initialization lists and those with values without having to provide both constructors myself; that is part of what I want.

// Example 1: default initialization
A a1;

The first example uses initialization; members a and b are undefined afterwards (not what I want, I want them to be value-initialized).

// Example 2: Value-initialization, so this works, I guess:
A a2 = A();

Example 2 uses value initialization and does not copy afterwards. So that is what I want, however, I also thought that empty brace-init-lists would do the same; see the following example:

// Example 3: list-initialization with empty brace-init-list
A a3{};

Example 3 is what I thought would do the trick. List initialization with an empty brace-init-list is described in 8.5.4 "List-initialisation":; especially 8.5.4.3 says: "If the initializer list has no elements and T is a class type with a default constructor, the objectvalue-initialized". However, this issues warnings with g++ 4.7.2 with -Wextra:

missing initializer for member ‘A::a’ [-Wmissing-field-initializers]
missing initializer for member ‘A::b’ [-Wmissing-field-initializers]

No warnings by clang++ 3.1, though, so it may also be a bug in g++.

So back to my original question. How do I value-initialize an object without having to provide my own boilerplatish default constructor -- while retaining the ability to use list-initialization for its members without having to provide my own initializer_list constructor?

like image 209
Moritz Bunkus Avatar asked Dec 25 '12 12:12

Moritz Bunkus


1 Answers

A plain struct like

struct A { int a,b; };

is clearly an aggregate, and A a {}; is clearly aggregate initialization and implies value-initialization (i.e. zero-initialization), as described by §8.5.4/3 quoted by you already. (Note in particular the example given there in the following paragraph, which is practically identical to your situation.)

The GCC warning is very misleading.

When searching for existing bug reports, I found this one, which you've filed yourself. I think that was the right thing to do.

Since you've worked out the relevant Standard sections already, and various other people contributed in the comments, I'll make this a Community Wiki answer.

like image 167
jogojapan Avatar answered Nov 11 '22 22:11

jogojapan