opérateur de flèche (->) dans l'en-tête de fonction

128

Je suis tombé sur le code suivant:

template <typename T, typename T1> auto compose(T a, T1 b) -> decltype(a + b) {
   return a+b;
}

Il y a une chose que je ne comprends pas:

Où pourrais-je trouver ce que signifie l'opérateur flèche ( ->) dans l'en-tête de fonction? Je suppose que de manière purement logique, l' ->opérateur détermine un type auquel autoil sera déduit, mais je veux clarifier les choses. Je ne trouve aucune information.

user1234567
la source
2
Cela fait partie de la syntaxe du type de retour de fin. Voir stackoverflow.com/a/4113390/962089
chris
2
Ce n'est pas un opérateur mais une partie de la syntaxe.
texasbruce
1
En réponse à «où puis-je lire?», La spécification C ++ fait le plus autorité. Faute de fonds ou désireux de dépenser $$, le dernier projet de travail est souvent assez proche et sans frais. Ces spécifications sont très techniques, donc manquant de familiarité avec la lecture des spécifications ISO, essayez cplusplus.com ou cppreference.com ou d'autres sites de ce type qui ne font pas autorité, mais sont généralement très précis. Remarque: le type de retour de fin peut être omis à partir de C ++ 14.
Les

Réponses:

205

En C ++ 11, il existe deux syntaxes pour la déclaration de fonction:

    déclarations d' arguments d' identificateur de type de retour ( ... )

et

    auto identifiant ( argument-déclarations ... ) -> return_type

Ils sont équivalents. Maintenant, quand ils sont équivalents, pourquoi avez-vous jamais envie d'utiliser ce dernier? Eh bien, C ++ 11 a introduit cette decltypechose intéressante qui vous permet de décrire le type d'une expression. Vous souhaiterez peut-être dériver le type de retour à partir des types d'argument. Alors vous essayez:

template <typename T1, typename T2>
decltype(a + b) compose(T1 a, T2 b);

et le compilateur vous dira qu'il ne sait pas quoi aet bsont dans l' decltypeargument. En effet, ils ne sont déclarés que par la liste d'arguments.

Vous pouvez facilement contourner le problème en utilisant declvalet les paramètres de modèle qui sont déjà déclarés. Comme:

template <typename T1, typename T2>
decltype(std::declval<T1>() + std::declval<T2>())
compose(T1 a, T2 b);

sauf que ça devient vraiment bavard maintenant. Ainsi, la syntaxe de déclaration alternative a été proposée et implémentée et vous pouvez maintenant écrire

template <typename T1, typename T2>
auto compose(T1 a, T2 b) -> decltype(a + b);

et c'est moins verbeux et les règles de cadrage n'ont pas besoin de changer.


Mise à jour C ++ 14: C ++ 14 permet également

    auto identifiant ( argument-déclarations ... )

tant que la fonction est entièrement définie avant utilisation et que toutes les returninstructions sont du même type. La ->syntaxe reste utile pour les fonctions publiques (déclarées dans l'en-tête) si vous souhaitez masquer le corps dans le fichier source. De toute évidence, cela ne peut pas être fait avec des modèles, mais il existe des types concrets (généralement dérivés via la métaprogrammation de modèles) qui sont difficiles à écrire autrement.

Jan Hudec
la source
2
réponse très bonne, soignée et informative @Jan Hudec. Ça bouge. Y a-t-il quelque chose de changé C++14lorsque j'utilise autopour returntaper dans une telle fonction sans avoir besoin de la -> decltype(a + b)pièce. Est-il redondant maintenant ou y a-t-il d'autres cas où il devrait encore être utilisé? ou est-ce une extension spécifique au compilateur?
Shadi
1
@Shadi, C ++ 14 inclut N3638 , qui permet la déduction du type de retour déclaré comme auto, sans la ->notation, tant que la fonction est entièrement définie avant utilisation et que toutes les returninstructions sont déduites du même type. La ->notation est toujours utile si vous souhaitez utiliser la déduction pour une fonction publique tout en masquant le corps dans le fichier source.
Jan Hudec
23

En clair, il indique que le type de retour est le type inféré de la somme de aet b.

Murrekatt
la source