2016-10-10 3 views
2

Avec l'introduction du type de retour auto en C++ 14, existe-t-il une situation réelle nécessitant un retour type ou est-il complètement obsolète en C++ 14 et 17?Type retour retour en C++ 14

+0

En dehors de ce qui a été déjà mentionné, traînante du type de retour vous permet également d'utiliser 'this' en retour types. – erip

Répondre

8

Tenez compte ...

auto f(int x) 
{ 
    if (x == 2) 
     return 3; 
    return 2.1; 
} 

... cela a un type de retour ambigu - int ou double. Un type de retour explicite - qu'il soit préfixe ou en fin de ligne - peut le désambiguïser et renvoie l'argument return au type de retour.

Trailing types de retour sont spécifiquement également utile si vous souhaitez utiliser decltype, sizeof etc sur certains arguments:

auto f(int x) -> decltype(g(x)) 
{ 
    if (x == 2) 
     return g(x); 
    return 2; 
} 
+0

Ce dernier exemple semble étrange. Pour comprendre le type de retour de 'f', il faut connaître le type de retour de' f'. Ne semble pas utile et [gcc ne l'aime pas] (http://ideone.com/4eDK25). – nwp

+1

@mwp: ahhh .. J'avais l'intention de leur faire différentes fonctions - merci de le signaler. –

+0

@Tony D: pourriez-vous éditer votre réponse et la rendre plus claire? Je n'ai pas compris votre point de vue et je n'ai pas pu appliquer votre exemple. – Shadi

9

Le type de retour arrière vous donne un support SFINAE. Les types de retour déduits ne provoquent jamais une erreur assez tôt pour être un simple échec de substitution.

Cela permet aux compilateurs de ne pas avoir à compiler des corps entiers de fonctions arbitraires, puis de revenir en arrière proprement afin de déterminer si une surcharge s'applique.

2

En dehors de l'endroit où vous devez l'utiliser (et les autres réponses ici donnent de bons exemples) , vous pouvez l'utiliser pour la clarté, pour explicitement indiquant ce que la fonction renvoie. Ceci est très important une fois que vous vous rendez compte (espérons-le bientôt) que la lecture d'un code est au moins aussi importante que l'écriture.

considèrent:

auto split(gsl::cstring_span str) 
{ 
    ... 
    ... 
    auto tokens = std::vector<gsl::cstring_span>(); 
    ... 
    ... 
    for (...) { 
     ... 
     ... 
     ... 
    } 
    ... 
    return tokens; 
} 

contre:

auto split(gsl::cstring_span str) -> std::vector<gsl::cstring_span>(); 
{ 
    ... doesn't even matter 
} 

Je ne devrais pas être à la recherche dans la mise en œuvre pour voir ce que le contrat de la fonction est. Je pourrais probablement deviner quel est le type de retour en regardant le premier exemple, mais ce genre d'hypothèses est dangereux en programmation. Je devrais scanner l'implémentation pour être sûr de ce que je reçois quand j'appelle la fonction. Avec le deuxième exemple, j'ai l'interface clairement indiquée. Je ne m'intéresse pas à la mise en œuvre, car le nom est auto-explicatif et je n'ai donc pas du tout à regarder dans la définition.

De plus, considérons cet exemple encore pire. Permet de savoir ce que cette fonction retourne:

auto split(const char* str) 
{ 
    return split(gsl::cstring_span(str)); 
} 

Ok, recherchez maintenant que la surcharge:

auto split(gsl::cstring_span str) 
{ 
    return split_impl(str); 
} 

Okey ..., laisse maintenant suivre que:

auto split_impl(gsl::cstring_span str) 
{ 
    return split_impl(str, ::isspace); 
} 

Êtes-vous f ** Je rigole.

Donc j'espère que vous voyez le point. Je ne dis pas toujours utiliser le type de retour explicite, je dis considérer que connaître le type de retour devrait être rapidement avec un simple coup d'oeil à la fonction. Parfois, pour one-liners, qui peut être découvert à partir du corps. Parfois, il peut être deviné en toute sécurité à partir du nom (par exemple is_empty() renvoie clairement bool). D'autres fois, vous auriez besoin de le nommer explicitement.Rendre plus simple la vie du développeur qui utilise votre code plus tard, d'autant plus que celui-ci finira par être inévitablement vous.