tuple
en boost y TR1/C++ 0x proporciona un método conveniente (para el escritor de la función) para devolver dos valores de una función, aunque parezca daños una característica importante de la lengua de la persona que llama: la capacidad de utilizar simplemente la función para inicializar una variable:Cómo inicializar con valores de retorno múltiples en C++ (0x)
T happy();
const auto meaningful_name(happy()); // RVO means no excess copies
pero para:
tuple<T,U> sad();
que o bien tienen que renunciar a la posibilidad de escoger una nombre significativo para nuestros valores de devolución, y use get<n>()
en todas partes:
const auto two_unrelated_things(sad());
o hacer un temporal:
const auto unwanted_named_temporary(sad());
const auto one_name(get<0>(unwanted_named_temporary));
const auto two_name(get<1>(unwanted_named_temporary));
o cambiar de inicialización de la asignación, que sólo funciona cuando los tipos son asignables, y se rompe auto
:
tuple_element<0, decltype(sad())>::type one_mutable; // there might be a less
tuple_element<1, decltype(sad())>::type two_mutable; // verbose way
tie(one_mutable,two_mutable) = sad();
o hacer algo antinatural a una clase local:
const struct ugh {
ugh(decltype(sad()) rhs) : one_name(get<0>(rhs)), two_name(get<1>(rhs)) {}
const tuple_element<0, decltype(sad())>::type one_name;
const tuple_element<1, decltype(sad())>::type two_name;
} stuff(sad()); // at least we avoid the temporary and get initialization
¿Hay una manera mejor? Estoy usando las construcciones compatibles con VC10 anteriores, ¿habría algo en C++ 0x completo o aumentaría la ayuda?
Lo ideal sería:
- me permite utilizar la inicialización, no sólo la asignación
- dejar que el persona que llama recoger los nombres de los
- no hacer copias adicionales devueltos-en variables
- trabajo para las variables de la pila y los miembros de la clase
- posiblemente sea una biblioteca de plantillas loca, pero tenga una sintaxis sana para el que llama y el escritor de funciones
Pregunta interesante, aunque no veo cómo podría definir variables de diferentes tipos en una sola expresión. - Creo que la opción "o hacer una temporal" podría estar bien, si cambias las variables nombradas a referencias (evitando copiar). – UncleBens
Buen punto sobre las referencias: creo que es una solución para las variables de pila. He intentado hacer lo mismo en una clase: clase C {public : C sr () (triste()), un (obtener <0> (SR)), dos (obtener <1> (SR)) {} const T & one; const U & two; privado: tupla sr; } Pero parece que en VC10, C es dos punteros más grande que la tupla, no es un gran problema sino un poco cojo: ¿no sería legal que el compilador reconozca que las referencias son alias y no asignan espacio en la instancia para ellos? ¿No es por eso que los indicadores de referencias son ilegales en primer lugar? –
BCoates
Con una clase, si los datos se almacenan como una tupla, podría simplemente proporcionar métodos de acceso con nombre, que llaman a los respectivos 'obtener'. Dudo que haya una solución basada en una "plantilla loca", porque el lenguaje central simplemente no parece respaldar lo que estás pidiendo. Tal vez podrías reducir el número de caracteres que tienes que escribir con macros ... –
UncleBens