tuple
dans boost et TR1/C++ 0x fournit une méthode pratique (pour l'auteur de la fonction) pour retourner deux valeurs d'une fonction - mais il semble dommage une caractéristique majeure de la langue de l'appelant: la possibilité d'utiliser simplement la fonction d'initialiser une variable:Comment initialiser avec plusieurs valeurs de retour en C++ (0x)
T happy();
const auto meaningful_name(happy()); // RVO means no excess copies
mais pour:
tuple<T,U> sad();
nous doivent soit renoncer à la possibilité de choisir un nom significatif pour nos valeurs de retour, et utilisez get<n>()
partout:
const auto two_unrelated_things(sad());
ou faire un temporaire:
const auto unwanted_named_temporary(sad());
const auto one_name(get<0>(unwanted_named_temporary));
const auto two_name(get<1>(unwanted_named_temporary));
ou passer d'initialisation à l'affectation, qui ne fonctionne que lorsque les types sont cessibles, et les pauses 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();
ou faire quelque chose contre nature à une classe locale:
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
Y a-t-il un meilleur moyen? J'utilise des constructions compatibles VC10 ci-dessus, est-ce que tout ce qui est en C++ 0x ou boost serait utile?
Idéalement, il serait:
- me permettre d'utiliser l'initialisation, non seulement l'affectation
- laisser le appelant choisir les noms pour les retournés-en variables
- pas faire des copies supplémentaires
- travailler pour les variables de pile et les membres de classe
- peut-être une grande bibliothèque de modèles fou, mais ont une syntaxe saine pour l'appelant et le rédacteur de fonctions
Question intéressante, bien que je ne vois pas comment vous pourriez définir des variables de types différents dans une seule expression. - Je pense que l'option "ou faire une temporaire" pourrait être OK, si vous changez les variables nommées en références (évitant la copie). – UncleBens
Bon point sur les références - Je pense que c'est une solution pour les variables de pile. J'ai essayé de faire la même chose dans une classe: classe C { public: C() sr (triste()), un (get <0> (sr)), deux (se <1> (sr)) {} const T & one; const U & two; privé: tuple sr; } Mais il semble que dans VC10, C est deux pointeurs plus gros que le tuple, pas très gros mais plutôt boiteux - ne serait-il pas légal que le compilateur reconnaisse que les références sont des alias et n'alloue pas d'espace dans le cas pour eux? N'est-ce pas pourquoi les références aux références sont illégales en premier lieu? –
BCoates
Avec une classe, si les données sont stockées en tant que tuple, vous pouvez simplement fournir des méthodes d'accès nommées, qui appellent les 'get' respectifs. Je doute qu'il y ait une solution basée sur un «modèle fou», parce que le langage de base ne semble tout simplement pas soutenir ce que vous demandez. Peut-être que vous pourriez simplement réduire le nombre de caractères que vous devez taper avec des macros ... –
UncleBens