In C++14:
For any integral or enumeration type T
and for any expression expr
:
Is there ever a difference between:
struct S { T t { expr }; };
and
struct S { T t = { expr }; };
Update:
I got to [dcl.init.list]p3b5
which says:
If the initializer list has a single element of type E and either T is not a reference type or its referenced type is reference-related to E, the object or reference is initialized from that element.
I believe this quote applies to both direct-list-initialization and copy-list-initialization.
So I think the answer is no, there is no difference.
If you take a look at direct initialization and copy initialization references, you will find the same words:
if T is a non-class type, standard conversions are used, if necessary, to convert the value of other to the cv-unqualified version of T
so there should be no difference. The difference of these initializations only applies for class types: copy initialization does not consider explicit
constructors and explicit
user-defined conversion operators, direct initialization does. Integral and enumeration types have neither of them.
Edit:
@ᐅ Johannes Schaub - litb ᐊ answered a relative question to this one (only about parentheses, instead of braces) and he referenced 8.5/14
with similar wording (emphasis mine):
The form of initialization (using parentheses or =) is generally insignificant, but does matter when the initializer or the entity being initialized has a class type; see below. If the entity being initialized does not have class type, the expression-list in a parenthesized initializer shall be a single expression.
I could not find the {}
counterpart in the standard, either. I hope that this is enough arguments to support the there's no difference answer.
struct S {T t { expr };};
is a non-static data member initializer
that does not use the equals sign.struct S{T t = { expr };};
is a non-static data member initializer
that uses the equals sign.The first case is a direct-list-initialization while the second is a copy-list-initialization.
The difference between direct-list-initialization and copy-list-initialization is that for the first case both explicit and non-explicit constructors are considered, while for the second only non-explicit constructors may be called.
To clarify, consider the following example:
struct Foo {
int i;
explicit Foo(int i_) : i(i_) {}
};
struct Bar {
Foo f {1};
};
Live Demo
In this example Foo
has an explicit
constructor and Bar
direct initializes its member f
of type Foo
. The example code compiles fine since for direct initialization both explicit
and non-explicit
constructors are considered.
Now we alter the example by transforming the non-static data member initializer with no use of equal sign, that is a case of direct-list-initialization to a non-static data member initializer with use of equal sign, which is a case of copy-list-initialization.
struct Foo {
int i;
explicit Foo(int i_) : i(i_) {}
};
struct Bar {
Foo f = {1};
};
Live Demo
Now the above example doesn't compile and emits an error:
error: chosen constructor is explicit in copy-initialization
This is expected because as already been mentioned in copy-list-initialization only non-explicit constructors may called.
Now for enumerators and other integral types, the difference displayed above won't apply (i.e., no constructors are involved). As such, the two statements (i.e., [1] and [2]) would be equivalent.
But for completeness sake, lets consider the following examples:
enum class Foo {A, B, C};
struct Bar {
Foo f{Foo::A};
};
and
enum class Foo {A, B, C};
struct Bar {
Foo f = {Foo::A};
};
Both the examples compile fine.
Also consider the following examples:
struct Bar {
int i {1};
};
and
struct Bar {
int i = {1};
};
Both examples also compile fine.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With