2016-02-08 3 views
3

У меня есть этот код:VARIADIC шаблон функции распаковывать порядка

template<typename ...T> 
struct Test 
{ 
    void call(string str) 
    { 
     abc(get<T>(str)...); 
    } 

    template<typename U> 
    string get(string& inp) 
    { 
     string ret{ inp[0] }; 
     inp.erase(0, 1); 

     cout << ret << endl; // first "a", next "b", next "c" - everything is ok 

     return ret; 
    } 

    void abc(string a, string b, string c) 
    { 
     cout << a << " " << b << " " << c << endl; // "b c a" - why? 
    } 
}; 

Я звоню это так:

Test<int, bool, float> test; 
test.call("abc"); 

И выход b c a думал, что я ожидал a b c. Кроме того, в функции get() у меня есть правильный порядок. Почему это? Я не могу найти никакого правила об этом заказе.

+3

Возможный дубликат [Порядок оценки в параметрах функций C++] (http://stackoverflow.com/questions/2934904/order-of-evaluation-in-c-function-parameters) –

+0

смотрите на http://en.cppreference.com/w/CPP/л nguage/eval_order в разделе неопределенного поведения. Что мне кажется наиболее актуальным для вашего случая, является примером: cout << i << i ++; который не определен. Я думаю, что каждый компилятор может выбрать, в каком порядке оценивать переменные. – Jonathan

+0

Я не думаю, что это должно быть закрыто как дубликат, так как решение этой проблемы сильно отличается для шаблона и кода без шаблонов. – TartanLlama

ответ

5

Порядок оценки аргументов функции не указан.

abc(get<T>(str)...); 

То есть по существу такой же, как:

abc(get<T1>(str), get<T2>(str), get<TN>(str)); 

Вы могли бы навести порядок оценки путем создания массива для хранения строк, то диспетчерские из этого массива:

template <std::size_t N, std::size_t... Idx> 
void call_helper(std::array<std::string, N> arr, std::index_sequence<Idx...>) { 
    abc(std::get<Idx>(arr)...); 
} 

void call(string str) 
{ 
    std::array<std::string,sizeof...(T)> arr { get<T>(str)... }; 
    call_helper(arr, std::index_sequence_for<T...>{}); 
} 
+0

Не могли бы вы объяснить, почему в создании массива порядок строгий? Что такое 'index_sequence' и' index_sequence_for'? Эти типы не определены int VS 2013. – nikitablack

+0

О, я не заметил, что они доступны, начиная с C++ 14 – nikitablack

+1

@nikitablack: Порядок оценки инициализаторов скобок определен, потому что стандарт говорит так, и ничего больше. Два символа, о которых вы спрашиваете, являются [частью стандартной библиотеки] (http://en.cppreference.com/w/cpp/utility/integer_sequence). – Deduplicator

2

Порядок аргументов вызова функции не гарантируется. Следовательно, abc(get<T>(str)...); не имеет определенного порядка.

Для получения более подробной информации см. Order of evaluation in C++ function parameters.