6

Suppose I have a unique_ptr member object that I want to initialize in-class, see the code below. Why do I have to use uniform initialization (curly braces)? The second declaration spits 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 is a most vexing parse issue, at least I don't believe so.

#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;
}
2
  • 4
    NSDMIs must use a brace-or-equal-initializer. Commented Oct 9, 2014 at 2:37
  • @T.C. thanks, I didn't know it's a must. Commented Oct 9, 2014 at 2:40

2 Answers 2

9

Because those are the rules. In-class initialisers must use "braces" or "equals"; in fact, the syntactical element is called a brace-or-equal-initializer.

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

I don't know why parentheses aren't allowed; perhaps to avoid the possibility of the initialisation looking like a function declaration. It can be annoying when there's a difference between direct and brace initialisation:

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
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, didn't know about the rule. The syntax is indeed quite annoying, especially the second line std::vector<int> good{6};, which doesn't do what one may think.
8

A non-static data member initializer (NSDMI) must use a brace-or-equal-initializer. The ( expression-list ) form of initialization isn't allowed.

As N2756 explains, in order to allow NSDMIs to behave more like traditional constructor member initializer lists, the names inside initializers are looked up in the scope of the entire class. Unfortunately, this means that allowing parentheses initializers would make it impossible to determine whether something is an initializer or a function declaration at the time the declaration is parsed:

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

struct Y {
    int i(x);    // function
    typedef int x;
};

The paper discussed a couple possible ways to fix this short of banning it altogether ("everything that can be a declaration is a declaration" or "it's not a type unless you say it's a type"), but neither is very appealing, and the potential confusion was deemed to outweigh the benefit of allowing this form of initialization.

1 Comment

Good point, I thought it may be some kind of most vexing parse issue, but couldn't come up with an example myself. Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.