Unique initialization inside the class

Suppose I have a unique_ptr member unique_ptr that I want to initialize in a class, see below code. Why should I use single initialization (curly braces)? The second declaration spits out an error, something like

 so.cpp:10:31: error: expected parameter declarator std::unique_ptr<Foo> upf2(new Foo); ^ so.cpp:10:31: error: expected ')' so.cpp:10:30: note: to match this '(' std::unique_ptr<Foo> upf2(new Foo); ^ 2 errors generated. 

And I don’t think this is the most unpleasant parsing problem, at least I don’t believe it.

 #include <memory> class Foo { }; class Bar{ std::unique_ptr<Foo> upf1{new Foo}; // works fine // std::unique_ptr<Foo> upf2(new Foo); // error here }; int main() { Bar bar; } 
+5
source share
2 answers

A non-stationary data element initializer (NSDMI) must use a parenthesis initializer or equal. The initialization form ( expression-list ) not allowed.

As N2756 explains, to allow NSDMI to behave like traditional constructor member initializer lists, the names inside the initializers are scanned throughout the class. Unfortunately, this means that resolving the initializers in parentheses does not allow us to determine if something is an initializer or a function declaration during the analysis of the declaration:

 // not real code struct X { int i(x); // initializer static int x; }; struct Y { int i(x); // function typedef int x; }; 

The document discussed several possible ways to fix this in order to prevent it at all ("everything that can be a declaration is a declaration" or "it is not a type if you do not say it as a type"), but none of them are very attractive , and the potential confusion was considered to outweigh the benefits of allowing this form of initialization.

+7
source

Because these are the rules. In-class initializers must use “curly braces” or “equal”; in fact, the syntax element is called sliding or peer-initializer.

 int equals = 42; // OK std::unique_ptr<Foo> braces{new Foo}; // Also OK 

I do not know why parentheses are not allowed; perhaps to avoid the possibility of initialization, similar to a function declaration. This can be annoying when there is a difference between direct and sliding initialization:

 std::vector<int> bad(6); // ERROR: parentheses not allowed std::vector<int> good{6}; // OK but not the same std::vector<int> ugly = std::vector<int>(6); // OK but ugly 
+9
source

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


All Articles