9 votes

Utilisations légitimes de la syntaxe du retour de fonction en fin de déclaration en tant que C++14

Y a-t-il vraiment une raison d'utiliser encore la syntaxe suivante :

template
auto access(T& t, int i)
  -> decltype(t[i])
{
    return t[i];
}

Maintenant que nous pouvons utiliser :

template
decltype(auto) access(T& t, int i)
{
    return t[i];
}

La syntaxe du type de retour en fin de fonction semble maintenant un peu redondante ?

19voto

Quincunx Points 1923

Les types de retour déduits ne sont pas adaptés à SFINAE. Cette surcharge sera tout simplement exclue de l'ensemble de surcharges si t[i] est invalide :

template
auto access(T& t, int i)
  -> decltype(t[i])
{
    return t[i];
}

Alors que cette surcharge ne le fera pas, ce qui entraînera une erreur :

template
decltype(auto) access(T& t, int i)
{
    return t[i];
}

Démo


De plus, vous pouvez rencontrer des problèmes avec des types de retour déduits en conflit. Imaginez que je veuille renvoyer un std::optional. Le code suivant ne compile pas car std::nullopt_t n'est pas le même type que std::optional :

#include  // Fonctionnalité de la bibliothèque standard C++17

template 
auto foo(T const& val)
{
    if (val.is_invalid()) return std::nullopt;
    return val.some_function_returning_an_optional();
}

Les types de retour en fin de fonction vous permettent de spécifier exactement le type des expressions à retourner :

template 
auto foo(T const& val)
    -> decltype(val.some_function_returning_an_optional())
{
    if (val.is_invalid()) return std::nullopt;
    return val.some_function_returning_an_optional();
}

Vous pourriez utiliser un type de retour en tête, mais cela nécessiterait l'utilisation de std::declval, ce qui rendrait la compréhension plus difficile :

template 
decltype(std::declval().some_function_returning_an_optional())
foo(T const& val)
{
    if (val.is_invalid()) return std::nullopt;
    return val.some_function_returning_an_optional();
}

Démo

7voto

einpoklum Points 2893

Oui, au moins trois raisons :

  1. Déclaration significative : Votre première variante a une déclaration qui me dit quel est le type de retour ; votre deuxième variante exige que je lise votre définition. Mais votre définition pourrait être dans un autre fichier, ou pas très claire.
  2. Contrainte de type ou conversion de type : Votre corps pourrait renvoyer quelque chose d'autre que l'expression T[i], et donc vous obtenez une contrainte de type ou une conversion de ce que le corps renvoie à ce que vous voulez obtenir.
  3. Compatibilité ascendante : Cela peut vous sembler trivial, mais essayez d'écrire une bibliothèque et de dire à vos utilisateurs "Oh, vous avez besoin d'un compilateur conforme à C++14 en raison de mes choix de syntaxe mignons".

Et il y a aussi une quatrième raison dans la réponse de Justin.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X