Почему операции в потоке выполняются в обратном порядке?

Экспериментировал с шаблонами и наткнулся на неожиданный порядок выполнения операций в потоке.

#include <iostream>

using namespace std;

template <class T>
int A(T a) {
    static int t = static_cast<int>(a);
    return t;
}

int main()
{
    cout << A(5) << " " << A(6) << " " << A(7.2) << " " << A(7) << " " << A(2.8);

    return 0;
}

я ожидал получить

5 5 7 5 7

но получил

7 7 2 7 2

Очевидно что функции выполнялись не в том порядке, в котором я ожидал, но почему именно так?


Ответы (2 шт):

Автор решения: αλεχολυτ

Порядок вычисления аргументов функции не специфицирован. Например, для функции void f(int i, int j) при вызове с передачей в вызов других функций для порождения значений i и j, т.е.:

f(g(), k());

Нет гарантии того, что сначала будет вызвана g(), а только потом k().

Ровно то же самое происходит в вашем случае. Порядок вывода задаётся << как слева направо, однако сам вызов функций, которые порождают значения для вызова - неспецифицирован. При условии наличия состояния (статическая переменная внутри) функции это и приводит к такому, на первый взгляд, странному поведению.

Начиная с C++17 это исправлено (именно для << и >>), и ваш код в нем будет работать правильно.

→ Ссылка
Автор решения: ТарасПрогер

Все из-за static. Как вы знаете статическая-переменная инициализируеться один раз. Второй раз - нет(остаеться предидущее значение). Компилятор создает 2 функции(одна с параметром double другая с параметром int).

То есть cout << A(5); это мы первый раз вызываем int-функцию и статическая переменная инициализируеться 5. Выводим на екран.

А второй раз вызвали - ту же самую функцию с интом-параметром! А статическая переменная уже была проиницализирована поэтому пропускаем присвоение нового числа и выводим старую пятерку!

cout << " " << A(7.2);  

Вот это совсем другая double-функция и мы даем значение 7. И тд.

С потоком выполнения все ОК

→ Ссылка