evaluation order initialization array in c++
Asked Answered
A

1

9

I like c++11 variadic templates, so I often write some little codes with it.

See this example:

#include <cstdio>
#include <type_traits>
#include <vector>

template< typename ... T >
auto make_vector(T ... t ) -> std::vector< typename std::common_type<T...>::type >
{
    std::vector< typename  std::common_type<T...>::type > v;
    v.reserve( sizeof...(T) );

    using list = int[];
    (void)list{ 0, ( (void)v.push_back(std::move(t)) ,0)... };
    //                |/ / / /
    //                --------
    //                 \-- How are evaluated v.push_back()s, sequentially or arbitrary ?
    return v;
}

int main()
{
    auto v = make_vector(2, 3.0, 'a', 7UL );

    for(auto e : v )
      printf("%.2lf ", e);

    printf("\n");

}

Q: Is evaluation order of initialization of array sequentially or arbitrary (or implementation defined, undefined behavior) ?

If make_vector is wrong, how me fix its?

Aaronaaronic answered 25/11, 2013 at 6:28 Comment(3)
@Khurshid: +1 for the question. As an aside, why push_back? Why not construct the vector directly? return {std::forward<typename std::common_type<T...>::type>(t)...};Resh
@GMan: Nope, braced-init-lists are specifically sequenced left-to-right, even if that evaluates to a normal constructor call. It has also always been left-to-right for aggregate initialization.Schertz
@Xeo: Read it as a function call for some reason, my mistake!Scholarship
T
13

They are evaluated sequentially. C++11 § 8.5.4 [dcl.init.list] paragraph 4:

Within the initializer-list of a braced-init-list, the initializer-clauses, including any that result from pack expansions (14.5.3), are evaluated in the order in which they appear.

Given that vector has an initializer_list constructor, you could simplify your function to:

template <typename ... T>
auto make_vector(T ... t) ->
  std::vector< typename std::common_type<T...>::type >
{
  return { static_cast<typename std::common_type<T...>::type>(t)... };
}

and not have to worry about arcane initialization semantics ;)

Tinishatinker answered 25/11, 2013 at 7:27 Comment(2)
Using std::forward you can do away with the cast too :)Resh
C11 port70.net/~nsz/c/c11/n1570.html#6.7.9p23 - The evaluations of the initialization list expressions are indeterminately sequenced with respect to one another and thus the order in which any side effects occur is unspecified.Noeminoesis

© 2022 - 2024 — McMap. All rights reserved.