The naive, optimistic and oh.. so wrong view of the c++11 uniform initialization syntax
I thought that since C++11 user-defined type objects should be constructed with the new {...}
syntax instead of the old (...)
syntax (except for constructor overloaded for std::initializer_list
and similar parameters (e.g. std::vector
: size ctor vs 1 elem init_list ctor)).
The benefits are: no narrow implicit conversions, no problem with the most vexing parse, consistency(?). I saw no problem as I thought they are the same (except the example given).
But they are not.
A tale of pure madness
The {}
calls the default constructor.
... Except when:
- the default constructor is deleted and
- there are no other constructors defined.
Then it looks like it it rather value initializes the object?... Even if the object has deleted default constructor, the {}
can create an object. Doesn't this beat the whole purpose of a deleted constructor?
...Except when:
- the object has a deleted default constructor and
- other constructor(s) defined.
Then it fails with call to deleted constructor
.
...Except when:
- the object has a deleted constructor and
- no other constructor defined and
- at least a non-static data member.
Then it fails with missing field initializers.
But then you can use {value}
to construct the object.
Ok maybe this is the same as the first exception (value init the object)
...Except when:
- the class has a deleted constructor
- and at least one data members in-class default initialized.
Then nor {}
nor {value}
can create an object.
I am sure I missed a few. The irony is that it is called uniform initialization syntax. I say again: UNIFORM initialization syntax.
What is this madness?
Scenario A
Deleted default constructor:
struct foo {
foo() = delete;
};
// All bellow OK (no errors, no warnings)
foo f = foo{};
foo f = {};
foo f{}; // will use only this from now on.
Scenario B
Deleted default constructor, other constructors deleted
struct foo {
foo() = delete;
foo(int) = delete;
};
foo f{}; // OK
Scenario C
Deleted default constructor, other constructors defined
struct foo {
foo() = delete;
foo(int) {};
};
foo f{}; // error call to deleted constructor
Scenario D
Deleted default constructor, no other constructors defined, data member
struct foo {
int a;
foo() = delete;
};
foo f{}; // error use of deleted function foo::foo()
foo f{3}; // OK
Scenario E
Deleted default constructor, deleted T constructor, T data member
struct foo {
int a;
foo() = delete;
foo(int) = delete;
};
foo f{}; // ERROR: missing initializer
foo f{3}; // OK
Scenario F
Deleted default constructor, in-class data member initializers
struct foo {
int a = 3;
foo() = delete;
};
/* Fa */ foo f{}; // ERROR: use of deleted function `foo::foo()`
/* Fb */ foo f{3}; // ERROR: no matching function to call `foo::foo(init list)`
Question&Answers:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…