para pagina oficial lenguaje historia dev descargar comandos basicos c++ templates c++11 parameters

pagina - historia de dev c++



¿Por qué la expansión del paquete de parámetros funciona de manera diferente con diferentes compiladores de C++? (2)

La expansión del paquete de parámetros se revierte mediante el compilador VS2015.

Tengo el siguiente código:

#include <iostream> #include <vector> template <typename... T> void f_Swallow(T &&...) { } template <typename... T> std::vector<int> f(T ...arg) { std::vector<int> result; f_Swallow ( [&]() { result.push_back(arg); return true; } ()... ) ; return result; } using namespace std; int main() { auto vec = f(1,2,3,4); for (size_t i = 0; i < vec.size(); ++i) cout << vec[i] << endl; }

Cuando ejecuto este código en XCode (clang-700.1.81), obtengo este resultado:

1 2 3 4

Pero el mismo código ejecutado en VS2015 produce esta salida:

4 3 2 1

¿Por qué los paquetes de parámetros se expanden de manera diferente según el compilador? ¿Hay alguna forma de solucionarlo sin consultar la plataforma y la versión del compilador? ¿El estándar no garantiza nada sobre la orden de expansión?


No es el orden de la expansión del paquete de parámetros lo que es diferente, es el orden de la evaluación del argumento de la función.

f_Swallow ( [&]() { result.push_back(arg); return true; } ()... ) ;

En aras de la brevedad, simplemente funcN esa lambda el nombre funcN donde N es el número del parámetro. Con cuatro argumentos, cualquier compilador conforme ampliará el paquete de parámetros a este:

f_Swallow(func1(), func2(), func3, func4()) ;

El orden de evaluación de los argumentos de la función no está especificado en C ++. El compilador podría evaluarlos en orden (como su versión de Clang), en orden inverso (como su versión de MSVC), o en cualquier orden que quiera. No puede contar con la orden de evaluación.

Para obtener lo que desea, puede colocar las expresiones en un contexto en el que se especifique el orden de evaluación. Por ejemplo:

template <typename... T> std::vector<int> f(T ...arg) { std::vector<int> result; (void)std::initializer_list<int> { (result.push_back(arg), 0)... }; return result; }

En C ++ 17, podrás hacer lo siguiente con expresiones fold :

template <typename... T> std::vector<int> f(T ...arg) { std::vector<int> result; (result.push_back(arg), ...); return result; }


Pensé que también podría escribirse así:

template <typename... T> std::vector<int> f(T ...arg) { std::vector<int> result{ arg... }; return result; }

No es necesario crear dummy std :: initializer_list