On 07.12.2018 15:57, Paul wrote:
> When I think of brace initialization I think of things like
> std::vector<int> v {3, 1, 2};
>
> I didn't realise though that this could be used with expressions.
> When I coded the below, I thought a compile error was likely but it worked fine. It seems that in the context of a definition which is also a declaration,
> the braces can replace the = sign. Is this correct? I've never seen it
> explained that way.
> For example, instead of const int sum = f(a, b, c);
> I can now write const int sum{f(a,b,c)};
> // Assume f is a function (int, int, int) -> int and that a, b, c
> // ints which are defined elsewhere.
You can also write
const int sum( f( a, b, c ) );
… but that form is more likely to attract the attention of the Most
Vexing Parse monster.
The Most Vexing Parse, disregarding Scott Meyers' original more limited
special case definition, is the rule that anything that /can/ be parsed
as a function declaration will be parsed as a function declaration.
---
The form
T v( args );
or
T v{ args };
is called /direct initialization/, and the form with `=`,
T v = something;
is called /copy initialization/.
---
Up till C++17 copy initialization required that a copy or move
constructor was accessible. With C++17 there is some pretty much
impenetrable formal language that requires the elision of actual copy or
move constructor calls in many cases, so that copy initialization can be
used even when the type is not copyable...
In C++03 there was no support for defining a class with constructor that
could be initialized with braces syntax.
When this support was added in C++11, via the `std::initializer_list`
type, the brace notation from old C was extended to usage also in direct
initialization syntax. Bjarne's goal or vision was that the braces
notation, the original notation from old C, should become a universal
initialization notation also in C++ (e.g., no more Most Vexing Parse, as
long as people just used the new universal notation). However, the
committee, or maybe he, anyway “They”™, bungled it with rules that mean
a constructor with `std::initializer_list` wins overload resolution,
unlike the more practical rules for other stuff where most specific
wins, e.g. `string{ 42, 'x' }` does not equal `string( 42, 'x' )`…
Cheers & hth.,
- Alf