2206. Inaccuracy in initializer_list constructor requirements

Section: 23.2.4 [sequence.reqmts], 23.2.7 [associative.reqmts], 23.2.8 [unord.req], 29.5.3.2 [rand.req.seedseq] Status: Open Submitter: Jeffrey Yasskin Opened: 2012-10-21 Last modified: 2020-09-06

Priority: 3

View other active issues in [sequence.reqmts].

View all other issues in [sequence.reqmts].

View all issues with Open status.

Discussion:

In 23.2.4 [sequence.reqmts] p3, we have "il designates an object of type initializer_list<value_type>", and then several functions that take 'il' as an argument. However, an expression like {1, 2, 'a'} is not an object of type initializer_list<int> unless it's used to initialize an explicitly-typed variable of that type. I believe we want:

std::vector<int> v;
v = {1, 2, 'a'};

to compile portably, so we should say something different when defining 'il'. The same phrasing happens in 23.2.7 [associative.reqmts], 23.2.8 [unord.req], and 29.5.3.2 [rand.req.seedseq].

This may just be an editorial issue because the actual class synopses declare the functions to take initializer_list<exact_type>.

[2013-03-15 Issues Teleconference]

Moved to Open.

This is definitely not NAD

Should copy the suggested wording as the proposed resolution.

[2019-03-26; Daniel comments and provides wording]

The 2013-03-15 comment is confusing, since it recommends to "copy the suggested wording as the proposed resolution". I couldn't find such wording in the issue nor in the associated wiki, so I provided that wording out of myself. The tricky part is to define which kind of braced-init-list we want to allow. As Tim Song pointed out, we still need the existing support for std::initializer_list<value_type> as well, because otherwise existing semantics based on expressions such as li.begin() won't work anymore. The below suggested wording restricts supported braced-init-lists to every initializer list that can be used to copy-list-initialize an object of type std::initializer_list<value_type> by saying:

"bil designates any braced-init-list suitable to copy-list-initialize an object of type initializer_list<value_type> (9.4.5 [dcl.init.list])"

As a drive-by fix, the provided wording adds another initialization "expression" that makes the construction of the form

std::vector<int> v = {1, 2, 'a'};

valid (We just miss a copy-initialization case).

Proposed resolution:

This wording is relative to N4810.

[Drafting note: We need to special-case the "expression" X u = bil; below, because for empty braced-init-list the effects are those of calling the default constructor. — end drafting note]

  1. Modify 23.2.4 [sequence.reqmts] as indicated:

    -3- In Tables 66 and 67, […] il designates an objectvalue of type initializer_list<value_type>, bil designates any braced-init-list suitable to copy-list-initialize an object of type initializer_list<value_type> (9.4.5 [dcl.init.list]), […]

  2. Modify Table 66 — "Sequence container requirements (in addition to container)" as indicated:

    Table 66 — Sequence container requirements (in addition to container)
    Expression Return type Assertion/note
    pre-/post-condition
    […]
    X(il)
    X u = il;
    Equivalent to X(il.begin(), il.end())
    or X u(il.begin(), il.end());, respectively
    X(bil) Equivalent to X(initializer_list<value_type>(bil))
    X u = bil; If bil is empty, equivalent to X u;, otherwise
    equivalent to X u = initializer_list<value_type>(bil);
    a = il X& […]
    a = bil X& Equivalent to a = initializer_list<value_type>(bil)
    […]
    a.insert(p, il) iterator […]
    a.insert(p, bil) iterator Equivalent to a.insert(p, initializer_list<value_type>(bil))
    […]
    a.assign(il) void […]
    a.assign(bil) void Equivalent to a.assign(initializer_list<value_type>(bil))
    […]
  3. Modify 23.2.7 [associative.reqmts] as indicated:

    -8- In Table 69, […] il designates an objectvalue of type initializer_list<value_type>, bil designates any braced-init-list suitable to copy-list-initialize an object of type initializer_list<value_type> (9.4.5 [dcl.init.list]), […]

  4. Modify Table 69 — "Associative container requirements (in addition to container)" as indicated:

    Table 69 — Associative container requirements (in addition to container)
    Expression Return type Assertion/note
    pre-/post-condition
    Complexity
    […]
    X(il)
    X u = il;
    same as X(il.begin(), il.end())
    or X u(il.begin(), il.end());, respectively
    same as X(il.begin(), il.end())
    or X u(il.begin(), il.end());, respectively
    X(bil) Equivalent to X(initializer_list<value_type>(bil))
    X u = bil; If bil is empty, equivalent to X u;, otherwise
    equivalent to X u = initializer_list<value_type>(bil);
    X(il,c) same as X(il.begin(), il.end(), c) same as X(il.begin(), il.end(), c)
    X(bil, c) Equivalent to X(initializer_list<value_type>(bil), c)
    a = il X& […] […]
    a = bil X& Equivalent to a = initializer_list<value_type>(bil)
    […]
    a.insert(il) void equivalent to a.insert(il.begin(), il.end())
    a.insert(bil) void Equivalent to a.insert(initializer_list<value_type>(bil))
    […]
    a.assign(il) void […]
    a.assign(bil) void Equivalent to a.assign(initializer_list<value_type>(bil))
    […]
  5. Modify 23.2.8 [unord.req] p11's bullet list as indicated:

    -11- In Table 70:

    1. (11.1) — […]

    2. […]

    3. (11.14) — il denotes a value of type initializer_list<value_type>,

    4. (11.?) — bil denotes any braced-init-list suitable to copy-list-initialize an object of type initializer_list<value_type> (9.4.5 [dcl.init.list]),

    5. […]

  6. Modify Table 70 — "Unordered associative container requirements (in addition to container)" as indicated:

    [Drafting note: There is a preexisting issue with Table 70, that there is no symbol u specified ("u denotes the name of a variable being declared"), so existing initialization forms with a named variable are currently always written as "X a[…]" where a is defined as "a denotes a value of type X", the wording below follows this existing practice but the author of this wording would like to kindly ask the Project Editor to introduce said symbol u and apply it to all existing and new such named initialization forms instead. — end drafting note]

    Table 70 — Unordered associative container requirements (in addition to container)
    Expression Return type Assertion/note
    pre-/post-condition
    Complexity
    […]
    X(il)
    X a = il;
    X Same as X(il.begin(), il.end())
    or X a(il.begin(), il.end());, respectively
    Same as X(il.begin(), il.end())
    or X a(il.begin(), il.end());, respectively
    X(bil) X Equivalent to X(initializer_list<value_type>(bil))
    X a = bil; X If bil is empty, equivalent to X a;, otherwise
    equivalent to X a = initializer_list<value_type>(bil);
    X(il, n) X Same as X(il.begin(), il.end(), n) Same as X(il.begin(), il.end(), n)
    X(bil, n) X Equivalent to X(initializer_list<value_type>(bil), n)
    X(il, n, hf) X Same as X(il.begin(), il.end(), n, hf) Same as X(il.begin(), il.end(), n, hf)
    X(bil, n, hf) X Equivalent to X(initializer_list<value_type>(bil), n, hf)
    X(il, n, hf, eq) X Same as X(il.begin(), il.end(), n, hf, eq) Same as X(il.begin(), il.end(), n, hf, eq)
    X(bil, n, hf, eq) X Equivalent to X(initializer_list<value_type>(bil), n, hf, eq)
    […]
    a = il X& […] […]
    a = bil X& Equivalent to a = initializer_list<value_type>(bil)
    […]
    a.insert(il) void Same as a.insert(il.begin(), il.end()). Same as a.insert(il.begin(), il.end()).
    a.insert(bil) void Equivalent to a.insert(initializer_list<value_type>(bil))
    […]
  7. Modify 29.5.3.2 [rand.req.seedseq] p2's bullet list as indicated:

    -2- A class S satisfies the requirements of a seed sequence if the expressions shown in Table 82 are valid and have the indicated semantics, and […] In that Table and throughout this subclause:

    1. (2.1) — […]

    2. (2.?) — u denotes the name of a variable being declared,

    3. […]

    4. (2.6) — il is a value of initializer_list<T>.;

    5. (2.?) — bil denotes any braced-init-list suitable to copy-list-initialize an object of type initializer_list<T> (9.4.5 [dcl.init.list]).

  8. Modify Table 82 — "Seed sequence requirements" as indicated:

    Table 82 — Seed sequence requirements
    Expression Return type Pre/post-condition Complexity
    […]
    S(il)
    S u = il;
    Same as S(il.begin(), il.end())
    or S u(il.begin(), il.end());, respectively
    same as S(il.begin(), il.end())
    or S u(il.begin(), il.end());, respectively
    S(bil) Equivalent to S(initializer_list<T>(bil))
    S u = bil; If bil is empty, equivalent to S u;, otherwise
    equivalent to S u = initializer_list<T>(bil);
    […]