tutorial smart remix programador online espaƱol curso c++ for-loop language-lawyer std-pair tie

c++ - remix - smart contracts ethereum



Usar std:: tie como rango para el objetivo de bucle (2)

Quiero hacer algo como lo siguiente:

//std::vector<std::pair<TypeA, TypeB>> someInitializingFunction(); { TypeA a; TypeB b; for (std::tie(a, b) : someInitializingFunction()) { // do stuff; } }

Sin embargo, este código no es válido porque, como dice el estándar, un rango basado en bucle se define como equivalente a:

{ auto && __range = range-init; for ( auto __begin = begin-expr, __end = end-expr; __begin != __end; ++__begin ) { for-range-declaration = *__begin; statement } }

Donde una declaración de rango se define como:

for-range-declaration: attribute-specifier-seq_ {opt} decl-specifier-seq declarator

Entonces, ¿qué me está frenando es que decl-specifier-seq no está marcado como opcional?

Por lo tanto, parece que debo recurrir al estilo antiguo para bucles para este a la:

std::vector<std::pair<TypeA, TypeB>> myList = someInitializingFunction(); { TypeA a; TypeB b; for (auto it = myList.begin(); it != myList.end(); ++it) { std::tie(a, b) = *it; // do stuff; } }

Pero parece un poco complicado desde el punto de vista sintáctico para lo que parece ser una tarea bastante común, desempaquetar el resultado de una llamada a función, que es válida en muchos otros contextos.

¿Hay alguna propuesta para agregar algo al lenguaje? ¿Es esta incluso una idea razonable? ¿Hay una mejor manera de hacer esto que estoy pasando por alto? ¿Estoy malinterpretando el estándar?

Obviamente, podría armar mi propia función para hacer esto, pero también es un poco complicado usarlo también.


¡Aún puedes usar range-for!

//std::vector<std::pair<TypeA, TypeB>> someInitializingFunction(); { TypeA a; TypeB b; for (auto& p : someInitializingFunction()) { std::tie(a, b) = p; // do stuff; } }

O const auto& p si no necesita / desea modificar p .

ACTUALIZACIÓN: con lo anterior, también puede mover los elementos a las variables vinculadas usando std::move

for (auto& p : someInitializingFunction()) { std::tie(a, b) = std::move(p); // do stuff; }

para lo cual su sintaxis propuesta puede no funcionar bien. Un ejemplo artificial:

for (std::tie(a, b) : std::move(someInitializingFunction())) {} // Note: std::move here is superfluous, as it''s already an r-value // (may also hinder some optimizations). Purely for demonstration purposes.

Con eso, no tiene la capacidad de mover los valores de los elementos a las variables vinculadas, ya que begin() , end() , etc. desde un contenedor de valor r no generará iteradores de movimiento. (Bueno, sí, podrías adaptar el contenedor a algo que devuelva iteradores de movimiento, pero esa sería una historia completamente nueva)


Desde el 03-21-2017, los enlaces estructurados son parte de C ++.

Esto permite hacer directamente lo siguiente:

//std::vector<std::pair<TypeA, TypeB>> someInitializingFunction(); for (auto [a, b] : someInitializingFunction()) { // do stuff; }