How is the general {} syntax of the build?

In talk about initialization lists , I realized that Stroustrup basically says that the new construction syntax with curly braces is supposed to be a common replacement for all previous build syntaxes

X x1(); // most vexing parse ... doesn't work as intended X x2(x1); X x3 = x1; X x4 = X(); 

Instead, the new syntax is supposed to be used evenly as a possible replacement that you can use in every situation ... again, what is the main message that I took from his conversation. Maybe I misunderstood him.

So the question is, how is the general syntax? Is it possible to never use the old construction in the new C ++ 11 code, or are there situations when you need to return?


This question was initiated / motivated when I came across the following error, which, in my opinion, is a compiler error (but I would be glad if you could fix it).

 struct X {}; int main() { X x; X& y{x}; // works with (x) X& z{y}; // works with (y) } 

which does not compile on g ++ 4.7.1 and does not work on ideone 4.5.1 .

 prog.cpp: In function 'int main()': prog.cpp:5:9: error: invalid initialization of non-const reference of type 'X&' from an rvalue of type '<brace-enclosed initializer list>' prog.cpp:6:9: error: invalid initialization of non-const reference of type 'X&' from an rvalue of type '<brace-enclosed initializer list>' 

Note that it works when I replace X with int .

+6
source share
1 answer

Brace initialization works wherever an initializer is used. There are situations when you must use parens to access a constructor that does not have access to the parenthesis initializer, but they are rare.

 std::vector<int> v(1,1); std::vector<int> v{1,1}; 

vector<int> has a specialized constructor that accepts two int and is therefore ambiguous with an attempt to construct a vector two int long. An ambiguous constructor exists only for backward compatibility. New classes should not be defined using any constructors that conflict with initializer_list.

Uncertainty is eliminated by the fact that the parenthesis initialization syntax prefers initializer_list constructors over other constructors that would otherwise match. If you want to allow ambiguity in favor of using the non-initializer_list constructor, you cannot use parenthesis initialization.


Bjarne Straustrup writes

The uniform use of {} initialization became possible only in C ++ 11, so the older C ++ code uses () and = initialization. Therefore, () and = may be more familiar to you. However, I don’t know the logical reason to prefer the notation (), except in the rare case when you need to distinguish between initialization with a list of elements and a list of constructor arguments.

- C ++ programming language, fourth edition Β§17.3.2.1


Your sample code is completely legal and should work as expected. The error you get is just a mistake in GCC. Clang and VC ++ 2012 accept the code.

+9
source

Source: https://habr.com/ru/post/925535/


All Articles