Выражения сгиба кажутся хорошим способом применить функцию к каждому элементу кортежа. Однако, если прикладная функция имеет побочные эффекты, порядок вызовов функций может быть важной проблемой.
Рассматривать:
#include <iostream>
template<typename... Ts>
void printStuff(Ts... args)
{
( ([](auto&& v) { std::cout << v << " "; })(args), ... );
std::cout << '\n';
}
int main()
{
printStuff("hello", 42, 1.5f);
// expected output: hello 42 1.5
}
это похоже на работу.
Но гарантирован ли здесь порядок оценки для лямбд, или я могу получить значения, которые отображаются в выводе? Изменится ли ответ, если я использовал другой оператор для объединения команд?
Раскладывание вправо над оператором расширяется следующим образом: ... (arg0 op (arg1 op arg2))
, Таким образом, хотя парены помогают, они ничего не гарантируют в отношении порядка отдельных элементов.
Поэтому все осталось до op
, И оператор запятой (который отличается от запятых, разделяющих аргументы функций), даже до C ++ 17, это точка жесткой последовательности. Это обеспечивает оценку слева направо без перекрестных разговоров.
Если бы вы использовали вместо +
, не было бы никаких гарантий последовательности. Так что это зависит от оператора, которого вы используете. C ++ 17 добавил еще несколько операторов, которые имеют строгие гарантии последовательности (<<
, например).
Других решений пока нет …