2013-11-25 6 views
9

Мне нравится C++ 11 вариационных шаблонов, поэтому я часто пишу с ним несколько небольших кодов.массив инициализации порядка оценки в C++

Смотрите этот пример:

#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: порядок вычисления инициализации последовательного массива или произвольной (или реализации определяется, неопределенное поведение)?

Если make_vector неправ, как я исправить его?

+1

@Khurshid: +1 к вопросу , Как в сторону, почему 'push_back'? Почему бы не построить вектор напрямую? 'return {std :: forward :: type> (t) ...};' – legends2k

+0

@GMan: Нет, скопированные-init-списки специально упорядочены слева направо, даже если это оценивает обычный вызов конструктора. Он также всегда был слева направо для агрегатной инициализации. – Xeo

+0

@Xeo: По какой-то причине прочитайте его как вызов функции, моя ошибка! – GManNickG

ответ

11

Они оцениваются последовательно. C++ 11 § 8.5.4 [dcl.init.list] Пункт 4:

В инициализаторе-листе из рамно-Init-листа, в инициализаторе-положении, включая любой что результат из пакетов (14.5.3) оценивается в том порядке, в котором они появляются.

vector Учитывая, что имеет initializer_list конструктор, можно упростить функцию:

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)... }; 
} 

и не придется беспокоиться о тайных семантиках инициализации;)

+1

С помощью 'std :: forward' вы можете покончить с литым тоже :) – legends2k

+0

Это классно! Благодарю. – Khurshid

 Смежные вопросы

  • Нет связанных вопросов^_^