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