C++0x, exact semantics of initializer_list<E>

Discussion in 'C++' started by SG, Jul 22, 2010.

  1. SG

    SG Guest

    Hi!

    In a Google tech talk, Bjarne Stroustrup answered an audience question
    about whether it is possible to return std::initializer_list objects
    from functions with "Yes.". However, after having read the relevant
    sections of the recent draft (N3090.pdf)...

    section 8.5.4 ("List initialization"):

    4 An object of type std::initializer_list<E> is constructed from an
    initializer list as if the implementation allocated an array of N
    elelemts of type E, where N is the number of elements in the
    initializer list. Each element of that array is copy-initialized
    with the corresponding element of the initializer list, and the
    std::initializer_list<E> object is constructed to refer to that
    array. [...] [Example:

    struct X {
    X(std::initializer_list<double> v);
    };
    X x{ 1,2,3 };

    The initialization will be implemented in a way roughly equivalent
    to this:

    double __a[3] = {double{1}, double{2}, double{3}};
    X x(std::initializer_list<double>(__a, __a+3));

    assuming that the implementation can construct an initializer_list
    object with a pair of pointers. -end example ]

    5 The lifetime of the array is the same as that of the
    initializer_list object. [ Example:

    typedef std::complex<double> cmplx;
    std::vector<cmplx> v1 = { 1, 2, 3 };
    void f() {
    std::vector<cmplx> v2{ 1, 2, 3 };
    std::initializer_list<int> i3 = { 1, 2, 3 };
    }

    For v1 and v2, the initializer_list object and array created for
    { 1, 2, 3 } have full-expression lifetime. For i3, the
    initializer_list object and array have automatic lifetime.
    -end example ] [ Note: The implementation is free to allocate the
    array in read-only memory if an explicit array with the same
    initializer could be so allocated. —end note ]

    section 18.9 ("Initializer lists")

    2 [...] Copying an initializer list does not copy the underlying
    elements.

    ....I have trouble figuring out whether Stroustrup was right or wrong.
    The standard doesn't require the compiler to store the array
    statically initialized in a read-only section. So, in the worst case
    the array has automatic storage and the array will be destroyed before
    the function returns (see implementation example from 8.5.4/4).

    std::initializer_list<double> foo() {
    return {1.0, 3.0};
    }

    equivalent to

    std::initializer_list<double> foo() {
    double __ila[2] = {1.0,3.0};
    return std::initializer_list<double>(ila,ila+2);
    }

    ?

    But this would be a contradiction to 8.5.4/5 because the life-time of
    the std::initializer_list surpasses the life-time of the array in this
    case -- at least when copy elision (RVO) is applied.

    So, my question is:
    Is returning an initializer_list from a function actually supposed to
    work reliably?
    I'm guessing the answer is "no".


    Cheers!
    SG
     
    SG, Jul 22, 2010
    #1
    1. Advertising

  2. * SG, on 22.07.2010 15:23:
    > Hi!
    >
    > In a Google tech talk, Bjarne Stroustrup answered an audience question
    > about whether it is possible to return std::initializer_list objects
    > from functions with "Yes.". However, after having read the relevant
    > sections of the recent draft (N3090.pdf)...
    >
    > section 8.5.4 ("List initialization"):
    >
    > 4 An object of type std::initializer_list<E> is constructed from an
    > initializer list as if the implementation allocated an array of N
    > elelemts of type E, where N is the number of elements in the
    > initializer list. Each element of that array is copy-initialized
    > with the corresponding element of the initializer list, and the
    > std::initializer_list<E> object is constructed to refer to that
    > array. [...] [Example:
    >
    > struct X {
    > X(std::initializer_list<double> v);
    > };
    > X x{ 1,2,3 };
    >
    > The initialization will be implemented in a way roughly equivalent
    > to this:
    >
    > double __a[3] = {double{1}, double{2}, double{3}};
    > X x(std::initializer_list<double>(__a, __a+3));
    >
    > assuming that the implementation can construct an initializer_list
    > object with a pair of pointers. -end example ]
    >
    > 5 The lifetime of the array is the same as that of the
    > initializer_list object. [ Example:
    >
    > typedef std::complex<double> cmplx;
    > std::vector<cmplx> v1 = { 1, 2, 3 };
    > void f() {
    > std::vector<cmplx> v2{ 1, 2, 3 };
    > std::initializer_list<int> i3 = { 1, 2, 3 };
    > }
    >
    > For v1 and v2, the initializer_list object and array created for
    > { 1, 2, 3 } have full-expression lifetime. For i3, the
    > initializer_list object and array have automatic lifetime.
    > -end example ] [ Note: The implementation is free to allocate the
    > array in read-only memory if an explicit array with the same
    > initializer could be so allocated. —end note ]
    >
    > section 18.9 ("Initializer lists")
    >
    > 2 [...] Copying an initializer list does not copy the underlying
    > elements.
    >
    > ...I have trouble figuring out whether Stroustrup was right or wrong.
    > The standard doesn't require the compiler to store the array
    > statically initialized in a read-only section. So, in the worst case
    > the array has automatic storage and the array will be destroyed before
    > the function returns (see implementation example from 8.5.4/4).
    >
    > std::initializer_list<double> foo() {
    > return {1.0, 3.0};
    > }
    >
    > equivalent to
    >
    > std::initializer_list<double> foo() {
    > double __ila[2] = {1.0,3.0};
    > return std::initializer_list<double>(ila,ila+2);
    > }
    >
    > ?
    >
    > But this would be a contradiction to 8.5.4/5 because the life-time of
    > the std::initializer_list surpasses the life-time of the array in this
    > case -- at least when copy elision (RVO) is applied.
    >
    > So, my question is:
    > Is returning an initializer_list from a function actually supposed to
    > work reliably?
    > I'm guessing the answer is "no".


    I'm guessing the answer is the same as for returning a pointer or reference.

    After all an initializer_list seems to be no more than two pointers.

    E.g. you might return an initializer list constructed from a static array, or
    one that was passed into the function.


    Cheers & hth.,

    - Alf

    --
    blog at <url: http://alfps.wordpress.com>
     
    Alf P. Steinbach /Usenet, Jul 22, 2010
    #2
    1. Advertising

  3. SG

    SG Guest

    On 22 Jul., 18:33, Alf P. Steinbach wrote:
    >
    > I'm guessing the answer is the same as for returning a pointer
    > or reference.
    >
    > After all an initializer_list seems to be no more than two
    > pointers.


    Judjung by the examples and comments, yes. And I guess that anything
    more complicated (array on stack OR heap with ref-counting) is not
    what the designers had in mind.

    > E.g. you might return an initializer list constructed from
    > a static array


    As far as I can tell initializer_list objects are only created via the
    list initialization syntax. In cases like {1,2,3} it should be easy
    for the compiler to create a static array (much like string literals)
    but this behaviour is not guaranteed, so, it doesn't seem to work
    reliably.

    Cheers,
    SG
     
    SG, Jul 22, 2010
    #3
  4. * SG, on 22.07.2010 19:14:
    > On 22 Jul., 18:33, Alf P. Steinbach wrote:
    >>
    >> I'm guessing the answer is the same as for returning a pointer
    >> or reference.
    >>
    >> After all an initializer_list seems to be no more than two
    >> pointers.

    >
    > Judjung by the examples and comments, yes. And I guess that anything
    > more complicated (array on stack OR heap with ref-counting) is not
    > what the designers had in mind.
    >
    >> E.g. you might return an initializer list constructed from
    >> a static array

    >
    > As far as I can tell initializer_list objects are only created via the
    > list initialization syntax. In cases like {1,2,3} it should be easy
    > for the compiler to create a static array (much like string literals)
    > but this behaviour is not guaranteed, so, it doesn't seem to work
    > reliably.


    Well, I read up on it.

    Initialization of an object O with initializer_list argument constructor, from a
    brace initializer, works /as if/ (my words) an array A is created with same
    lifetime as the initializer_list formal constructor argument, that array A is
    initialized from the brace initializer, and the initializer_list object is set
    to point to begin and end of that array A.

    Since initializer_list objects are copyable initializer_list has a copy
    constructor, hence an initializer_list object can be initialized from a brace
    initializer, hence, what about just a 'static std::initializer_list<T> O = ..."?

    However, then we're into non-normative example territory.

    For formally the initializer_list object that governs the lifetime of the array
    would be the copy constructor's object, which doesn't exist very long, so the
    array A would only have full-expression lifetime. However, the non-normative
    example in §8.5.4/5 makes the claim that when the object O that is initialized
    by a brace expression is itself of type initializer_list, then the array has the
    same lifetime as O (and not just as its copy constructor formal argument).

    Anyway, this seems to work with g++ 4.4.1, while MSVC 10.0 chokes on its own
    <initializer_list> header.


    Cheers,

    - Alf

    --
    blog at <url: http://alfps.wordpress.com>
     
    Alf P. Steinbach /Usenet, Jul 22, 2010
    #4
  5. SG

    Dilip Guest

    On Jul 22, 1:05 pm, "Alf P. Steinbach /Usenet" <alf.p.steinbach
    > wrote:
    >
    > Anyway, this seems to work with g++ 4.4.1, while MSVC 10.0 chokes on its own
    > <initializer_list> header.


    Alf

    Take a look at this link:
    http://channel9.msdn.com/shows/Goin...Template-Library-STL-2-of-n/?CommentID=562782

    That post includes a comment from Stephen T Lavavej (owner of STL at
    Microsoft) at the very end. He says:

    > btw, will the initializer list be implemented in visual studio soon ?

    Magic 8 Ball says: "Ask again later."
    (I really want initializer lists, but they're actually not in my top
    three list of desired features. Also, please ignore the
    <initializer_list> header that I accidentally left in VC10 RTM. It
    doesn't do anything.)
     
    Dilip, Jul 23, 2010
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. J
    Replies:
    1
    Views:
    311
    Kevin Spencer
    Aug 20, 2003
  2. Sarath
    Replies:
    9
    Views:
    449
    Pete Becker
    Mar 3, 2007
  3. Rodolfo Lima
    Replies:
    0
    Views:
    325
    Rodolfo Lima
    Jun 28, 2010
  4. Elias Salomão Helou Neto
    Replies:
    6
    Views:
    473
    Vladimir Jovic
    Jul 28, 2010
  5. Wolfgang Thomas

    Regex: Exact semantics of ^ and $ when using /m

    Wolfgang Thomas, Jun 24, 2006, in forum: Perl Misc
    Replies:
    5
    Views:
    134
    Wolfgang Thomas
    Jun 25, 2006
Loading...

Share This Page