32

I asked a question here: Lifetime Extension of a initializer_list return involving the non-functional code:

const auto foo = [](const auto& a, const auto& b, const auto& c) { return {a, b, c}; };

I believed the lambda was trying to return an intializer_list (that's bad, don't do that.) But I got a comment:

It's not an initializer_list, it's an initializer list. Two different things.

I just thought that any time you did a curly-braced list you were creating an intializer_list. If that's not what's happening, what is a list in curly-braces?

Community
  • 1
  • 1
Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
  • It's just: error: returning initializer list. –  Jun 07 '16 at 14:57
  • 1
    @DieterLücking You must have your errors turned up higher than I do. I didn't even get a warning the first time I tried this, though as stated in the linked question this is *not* good code. – Jonathan Mee Jun 07 '16 at 15:02
  • @JonathanMee Below SO question has also some useful-to-know answers: http://stackoverflow.com/questions/29200036/is-providing-a-private-constructor-for-initializer-list-conforming – Arunmu Jun 07 '16 at 15:03
  • 1
    @Arunmu Are you saying these are just good to know related to `initializer_list`? Cause if you're saying it directly pertains, I'm missing how. – Jonathan Mee Jun 07 '16 at 15:08
  • @JonathanMee Yeah, just good to know :). I had no idea there was some compiler magic required to make initializer_list instances :) – Arunmu Jun 07 '16 at 15:17
  • @op could you do something about the Title Case in your question's title? It's not improving readability. – user1306322 Jun 07 '16 at 20:58
  • @user1306322 If you can cite a http://www.stackoverflow.com standard for titles I'll fix this and all future titles. I'm using [Title Case](https://en.wikipedia.org/wiki/Letter_case#Headings_and_publication_titles) which I thought was standard. – Jonathan Mee Jun 07 '16 at 21:33
  • I could google up something about capital letters disrupting the readability, but it's all subjective and there's no "official" standards on it on the internet. Just my observation. If you disagree, I'm not gonna argue. – user1306322 Jun 07 '16 at 21:40

4 Answers4

30

It is an braced-init-list. A braced-init-list existed before std::initializer_list and is used to initialize aggregates.

int arr[] = {1,2,3,4,5};

The above used a braced-init-list to initialize the array, no std::initializer_list is created. On the other hand when you do

std::vector<int> foo = {1,2,3,4,5};

foo is not an aggregate so the braced-init-list is used to create a std::initializer_list which is in turned passed to the constructor of foo that accepts a std::initializer_list.

A thing to note about a braced-init-list is that is has no type so special rules were developed for use with it and auto. It has the following behavior (since the adoption of N3922)

auto x1 = { 1, 2 }; // decltype(x1) is std::initializer_list<int>
auto x2 = { 1, 2.0 }; // error: cannot deduce element type
auto x3{ 1, 2 }; // error: not a single element
auto x4 = { 3 }; // decltype(x4) is std::initializer_list<int>
auto x5{ 3 }; // decltype(x5) is int

And you can get more information on history of this behavior and why it was changed at: Why does auto x{3} deduce an initializer_list?

Community
  • 1
  • 1
NathanOliver
  • 171,901
  • 28
  • 288
  • 402
13

There are three distinct, but related concepts here:

  1. braced-init-list: The grammatical rule associated with curly-brace-enclosed lists in certain contexts.

  2. Initializer list: The name for the braced-init-list initializer used in list-initialization.

  3. std::initializer_list: A class wrapping a temporary array which is created in some contexts involving braced-init-lists.

Some examples:

//a braced-init-list and initializer list, 
//but doesn't create a std::initializer_list
int a {4}; 

//a braced-init-list and initializer list,
//creates a std::initializer_list
std::vector b {1, 2, 3};

//a braced-init-list and initializer list,
//does not create a std::initializer_list (aggregate initialization)
int c[] = {1, 2, 3};

//d is a std::initializer_list created from an initializer list
std::initializer_list d {1, 2, 3};

//e is std::initializer_list<int>
auto e = { 4 };

//f used to be a std::initializer_list<int>, but is now int after N3922
auto f { 4 };

You might want to read N3922, which changed some of the rules involving auto and std::initializer_list.

TartanLlama
  • 63,752
  • 13
  • 157
  • 193
7

I just thought that any time you did a curly-braced list you were creating an intializer_list.

That's not correct.

If that's not what's happening, what is a list in curly-braces?

struct Foo {int a; int b;};
Foo f = {10, 20};

The {10, 20} part is not an initializer_list. It's just a syntactic form to use a list of objects to create another object.

int a[] = {10, 20, 30};

Once again, it's a syntactic form to create an array.

The name for the syntactic form is braced-init-list.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
1

You have two different things when use {}

  1. A Type std::initializer_list<T> where the values can be implicitly converted to T
  2. A type that can be initialized with the values of the list.

The first type forces a homogeneous list and the second type don't. In the next example:

struct S{ 
    int a; 
    string b 
};

void f1( S s );
void f2( int i );
void f3( std::initializer_list<int> l );

f1( {1, "zhen"} ); // construct a temporal S
f2( {1} );         // construct a temporal int
f3( {1,2,3} );     // construct a temporal list of ints

The functions f1 and f2 use the first type and f3 use the second type. You should know that if there is ambiguity, the std::initializer_list is prefered. E.g:

void f( S s );
void f( int i );
void f( std::initializer_list<int> l );

f( {1, "zhen"} ); // calls with struct S
f( {1} );         // calls with int list with one element
f( {1,2,3} );     // calls with int list with three elements
Zhen
  • 4,171
  • 5
  • 38
  • 57