Now we have five forms of initialization. They are
T x = expression; T x = ( expression ); T x ( expression ); T x = { expression }; T x { expression };
Each form has its own characteristics. :)
For example, suppose you have the following declarations in the global namespace
int x; void f( int x ) { ::x = x; } int g() { return x ; } long h() { return x; }
then basically you can write
int main() { int x ( g() ); }
This code will be compiled successfully.
However, the programmer mistakenly made a typo
int main() { int x; ( g() ); ^^ }
Oops! This code also compiles successfully. :)
But if the programmer writes
int main() { int x = ( g() ); }
and then create a typo
int main() { int x; = ( g() ); ^^ }
then in this case the code will not compile.
Suppose the programmer decided to first set a new value for global variabel x before initializing the local variable.
So he wrote
int main() { int x ( f( 10 ), g() ); }
But this code does not compile!
Insert equal sign
int main() { int x = ( f( 10 ), g() ); }
Now the code compiles successfully!
What about braces?
Neither this code
int main() { int x { f( 10 ), g() }; }
and this code
int main() { int x = { f( 10 ), g() }; }
compiles!)
Now the programmer decided to use the h () function, he wrote
int main() { int x ( h() ); }
and his code compiles successfully. But after some time he decided to use braces
int main() { int x { h() }; }
Oops! Its compiler gives an error message
error: a non-constant expression cannot be narrowed from type 'long' to 'int' in the initialization list
The program decided to use an auto type specifier. He tried two approaches
int main() { auto x { 10 }; x = 20; }
and
int main() { auto x = { 10 }; x = 20; }
and ... some compilers did not compile the first program, but did not compile the second program, and some compilers did not compile both programs. :)
What about using decltype ?
For example, a programmer wrote
int main() { int a[] = { 1, 2 }; decltype( auto ) b = a; }
And its compiler throws an error!
But when the programmer enclosed a in parentheses like this
int main() { int a[] = { 1, 2 }; decltype( auto ) b = ( a ); }
The code compiled successfully! :)
Now the programmer decided to study OOP. He wrote a simple class
struct Int { Int( int x = 0 ) : x( x ) {} int x; }; int main() { Int x = { 10 }; }
and his code compiles successfully. But pogrammer knew that an explicit function specifier existed, and he decided to use it
struct Int { explicit Int( int x = 0 ) : x( x ) {} int x; }; int main() { Int x = { 10 }; }
Oops! Its compiler issued an error
error: chosen constructor is explicit in copy-initialization
The programmer decided to remove the destination sign
struct Int { explicit Int( int x = 0 ) : x( x ) {} int x; }; int main() { Int x { 10 }; }
and his code compiled successfully! :)