Секвенирование среди расширения вариативных


Для этого невариадического примера:

int     Func1();
double  Func2();
void    MyFunc( int, double );

int  main()
{
    MyFunc( Func1(), Func2() );
    //...
}

Не указано, вычисляется ли сначала Func1() или Func2(), просто то и другое должно быть сделано до вызова MyFunc().

Как эта последовательность работает с расширением вариадических аргументов?

template < typename Func, typename ...Args >
void  MyFunc2( Func &&f, Args&& ...a )
{
    int  b[] = { f( std::forward<Args>(a) )... };
    //...
}

Предположим, что f - это объект функции, который изменяет свое состояние после первого вызова. Будет ли f вызываться по порядку для каждого сегмента a? Другими словами, будет ли f вызываться по первому пункту в списке a, затем второй пункт, третий и т. д., вместо того, чтобы случайно пропустить расширенный список? Есть ли то, что мы привыкли называть точками последовательности между каждым элементом?

1 5

1 ответ:

Да, заключенные в скобки списки инициализаторов гарантируют порядок вычисления слева направо, в то время как вызовы функций этого не делают. Так что MyFunc2 будет следовать правильно.

Статья Википедии описывает это: https://en.wikipedia.org/wiki/Variadic_templates

Есть ли то, что мы привыкли называть точками последовательности между каждым элементом?

Нет, хотя он использует знак запятой, это не оператор запятой.