Quelle est la meilleure façon de retourner un tuple de la fonction en C++11?
Je veux retourner certaines valeurs d'une fonction et je veux l'emballer dans un tuple. J'ai donc deux possibilités de déclaration de fonction:
std::tuple<bool, string, int> f()
{
...
return std::make_tuple(false, "home", 0);
}
Et
std::tuple<bool, string, int> f()
{
...
return std::forward_as_tuple(false, "home", 0);
}
Ces fonctions sont équivalentes? Entre ces fonctions Que préférez-vous?
2 réponses
std::forward_as_tuple()
crée un tuple de références. Puisque vous renvoyez un tuple<bool, string, int>
de toute façon, les deux finissent par être équivalents dans ce cas, mais je pense que la première approche est plus claire-utiliser forward_as_tuple()
lorsque vous ne transmettez rien est source de confusion.
Aussi, comme mentionné par Sebastian Redl dans les commentaires, make_tuple()
permettrait au compilateur d'effectuer une élision de copie - par paragraphe 12.8/31 de la norme C++11, alors que forward_tuple()
ne le ferait pas (puisque ce qu'il retourne n'a pas le même type que le type de retour de la fonction).
Je préfère,
std::tuple<bool, std::string, int> f()
{
...
return { false, "home", 0 };
}
Modifier 1
Le code ci-dessus est en train de compiler pour moi sous clang/libc++ trunk. Comme @ AndyProwl a commenté dans la section commentaires, cela ne devrait pas puisque le constructeur std:: tuple est explicite et le retour par la syntaxe initialization-list est dans le contexte copy-initialization, donc copy-list-initialization, qui échoue quand un constructeur explicite est apparié.
Je ne connais pas la raison pour laquelle clang / libc++ passe, je suppose que c'est un bug dans libc++. Quoi qu'il en soit, c'est triste de ne pas pouvoir faire ça pour les tuples...
Je pense que j'ai réalisé à quel point c'est triste (pour moi, enfin), en général. Je m'habituais à cette syntaxe, mais on est obligé de savoir à l'avance si le type de retour contient un constructeur explicite à tout moment pour que cela fonctionne.
Modifier 2
Ceci est en effet une extension libc++, pour plus d'informations, checkout Howard Hinnant réponse ici: https://stackoverflow.com/a/14963014 .
Il est également ouvert en la liste des bogues de libc++: http://llvm.org/bugs/show_bug.cgi?id=15299 .
C'est la proposition pertinente: Daniel Krügler, améliorer la paire et le tuple.
Bref, c'est ce qui se passe avec libc++:
#include <tuple>
#include <string>
struct S
{
explicit S(int) {}
};
int main()
{
std::tuple<int, std::string> t1 = { 1, "hello" }; // ok
std::tuple<std::string> t2 = "hello"; // ok
std::tuple<int, S> t3 = { 1, 1 }; // fail: an *element* is to be constructed explicitly
}