1

I just got caught by this seemingly innocent attempt to call the std::string constructor that takes a size and a character value, using uniform initialization syntax:

std::string s{ 10, '\0' };

I thought this would create a string with the length of 10, initialized with \0.

Though it actually calls the constructor that takes an initializer list and thus creates a string with the length of 2, initialized with {'\n', '\0'}!

See demo at Coliru.

Is there a way to avoid this pitfall when using uniform initialization? Or do I just have to be careful?

Note: Similar question has been asked before, but no answer was given on how to avoid that pitfall.

3
  • 3
    I think the wikipedia entry on uniform initialization describes it nicely: "Uniform initialization does not replace constructor syntax, which is still needed at times. If a class has an initializer list constructor (TypeName(initializer_list<SomeType>);), then it takes priority over other forms of construction, provided that the initializer list conforms to the sequence constructor's type." Commented May 10, 2017 at 22:03
  • @clcto Compiler seems to be eager to use initializer list constructor, even if the list consist of non-conforming types (Coliru example). To be fair there is a compiler warning. Commented May 10, 2017 at 22:09
  • 1
    @zett42: For the record, that behaviour is guaranteed by [over.match.list]/1; basically; constructors are looked up in two phases and if any initializer-list constructors exist at all then that's what you get, for better or for worse. Commented May 10, 2017 at 22:14

1 Answer 1

9

You just have to be careful.

In general, when people tell you to "use uniform initialisation so that everything is consistent and, well, uniform", ignore them. I mean, by all means use uniform initialisation, but don't believe that fairytale.

Also, ignore the name of the feature.

xkcd #927: "Standards"

Sign up to request clarification or add additional context in comments.

2 Comments

Well, the feature isn't officially named "uniform initialization" in the standard (or unicorn, for that matter).
To be fair, list initialization didn't have to work out this way. It could have subsumed all forms of initialization, if the committee had not make two mistakes: the preference for initializer_list constructors and forbidding narrowing conversions. Remove both of those, and you could legitimately replace any case of () initialization with {}.

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.