Le type de retour fait-il partie de la signature de la fonction?

En C++, est le type de retour considérés comme faisant partie de la signature de la fonction? et aucune surcharge n'est autorisée avec le type de retour modifié.

61
demandé sur yesraaj 2008-11-14 16:17:16

3 réponses

les fonctions normales ne comprennent pas le type de retour dans leur signature.

( note : j'ai réécrit cette réponse, et les commentaires ci - dessous ne s'appliquent pas à cette révision-voir l'édition-historique pour plus de détails).

Introduction

cependant, la question des fonctions et des déclarations de fonction dans la norme est compliquée. Il y a deux couches qui doivent être considéré:

  • déclarations
  • Entités

la soi-disant déclaration de fonction peut déclarer une entité de fonction ou un modèle d'entité. Si une fonction entité est déclarée, alors vous avez à faire avec une spécialisation explicite d'un modèle de fonction (avec tous les arguments spécifiés), ou une déclaration d'une fonction ordinaire. Si une entité modèle est déclarée, alors vous êtes déclarer un modèle de fonction primaire, ou une spécialisation explicite lorsque certains arguments ne sont pas spécifiés. (Ceci est très similaire à la relation entre "déclaration d'objet" et objets ou références: les premiers peuvent déclarer soit un objet, soit une référence. Ainsi, une déclaration d'objet ne peut pas nécessairement déclarer un objet!).

la norme définit la signature d'une fonction comme suit: 1.3.10 :

les types de ses paramètres et, si la fonction est un membre de classe, les qualificatifs cv (le cas échéant) sur la fonction elle - même et la classe dans laquelle la fonction membre est déclarée. La signature d'une spécialisation de modèle de fonction inclut les types de ses arguments de modèle. (14.5.5.1)

il manque le type de retour dans cette définition, qui est partie de la signature d'une spécialisation de modèle de fonction (I. e a déclaration de fonction qui déclare une fonction qui est une spécialisation d'un modèle), comme souligné par 14.5.5.1 (récents documents de travail c++0x fixé que déjà pour mentionner le type de retour dans 1.3.10 aussi):

la signature d'une spécialisation de modèle de fonction consiste en la signature du modèle de fonction et des arguments de modèle réels (qu'ils soient explicitement spécifiés ou déduits).

la signature d'un le modèle de fonction se compose de sa signature de fonction, de son type de retour et de sa liste de paramètres de modèle.

alors qu'est-ce qu'une signature contient exactement, encore une fois?

ainsi, quand nous demandons au sujet de la signature d'un fonction , nous devons donner deux réponses:

  • pour les fonctions qui sont des spécialisations de gabarits de fonction, la signature inclut le type de retour.
  • pour les fonctions qui ne sont pas des spécialisations, le type de retour ne fait pas partie de la signature.

avis, cependant, que le type de retour, dans tous les cas, est une partie importante du type d'une fonction. Qui est, le suivant n'est pas valide:

void f();
int (*pf)() = &f; // different types!

quand une surcharge est-elle invalide si seul le type de retour diffère?

principaux compilateurs rejettent actuellement le code suivant:

int f();
double f(); // invalid

mais accepter le code suivant:

template<typename T> int f();
template<typename T> double f(); // invalid?

cependant, la norme interdit une déclaration de fonction qui ne diffère que par le type de retour (lorsqu'il s'agit de définir quand une surcharge est valide, et quand elle ne l'est pas). Il ne définit pas précisément ce qui "diffère seulement par le type de retour" signifie, cependant.


références au paragraphe Standard:

  • quand une déclaration de fonction peut être surchargée: 13.1
  • Qu'est-ce qu'une déclaration de fonction: 7/2 et 7/5
  • Qu'est-ce que la signature d'un modèle de fonction/spécialisation: 14.5.5.1

pour référence, voici ce que le plus récent projet C++0x n3000 dit de "signature" dans 1.3.11 , qui est beaucoup plus complet dans sa couverture des différents types d'entités:

le nom et la liste type de paramètre (8.3.5) d'une fonction, ainsi que la classe ou de l'espace dont il est membre. Si une fonction ou un modèle de fonction est un membre de classe, sa signature inclut également les qualificatifs cv (s'il y a lieu) et ref-qualificatifs (s'il y a lieu) sur le modèle de fonction ou de fonction lui-même. La signature d'un modèle de fonction inclut en outre son type de retour et sa liste de paramètres de modèle. La signature d'une fonction la spécialisation de modèle inclut la signature du modèle dont il est une spécialisation et ses arguments de modèle (qu'ils soient explicitement spécifiés ou déduits). [ Note: les Signatures sont utilisées comme base pour la modification des noms et l'établissement de liens. - fin de la note ]

79
répondu Johannes Schaub - litb 2009-12-18 12:09:20

cela dépend si la fonction est un modèle de fonction ou non.

Dans C++ Templates -- la complète guides , Jusuttis fournit une définition différente de celle donnée dans la norme C++, mais avec les mêmes conséquences:

nous définissons la signature d'une fonction comme l'information suivante:

  1. le nom sans réserve de la fonction
  2. Le classe ou espace de noms la portée de ce nom, et si le nom a une liaison interne, l'unité de traduction dans lequel le nom est déclaré
  3. la const , volatile , ou const volatile qualification de la fonction
  4. les types des paramètres de fonction
  5. son retour type , si la fonction est générée à partir d'un modèle de fonction
  6. les paramètres du modèle et les arguments du modèle , si la fonction est générée à partir d'un modèle de fonction

Comme litb , a suggéré, il vaut la peine de préciser pourquoi le type de retour est une partie de la signature d'une fonction de modèle.

Les fonctions peuvent coexister dans un programme si ils ont des signatures distinctes.

. Cela dit, si le type de retour est un paramètre de template:

template <typename T>
T foo(int a)
{return T();}

il est possible d'instancier deux fonctions qui diffèrent seulement dans le type de retour:

foo<int>(0);
foo<char>(0);

non seulement: comme indiqué à juste titre par litb , il est également possible de surcharger deux fonctions de gabarit, qui diffèrent seulement dans le type de retour, même si le type de retour n'est pas un nom dépendant. Voici son exemple:

template<class T> int foo(T)
{}

template<class T> bool foo(T)
{}

// at the instantiation point it is necessary to specify the cast
// in order not to face ambiguous overload

((int(*)(char))foo<char>)('a'); 
10
répondu Nicola Bonelli 2008-11-15 12:14:34

ils sont assez une partie du type que vous pouvez surcharger les fonctions basées sur les types de pointeur de fonction qui diffèrent seulement par le type de retour:

int IntFunc() { return 0; }
char CharFunc() { return 0; }

void FuncFunc(int(*func)()) { cout << "int\n"; }
void FuncFunc(char(*func)()) { cout << "char\n"; }


int main()
{
    FuncFunc(&IntFunc); // calls void FuncFunc(int_func func)
    FuncFunc(&CharFunc); // calls void FuncFunc(char_func func)
}
2
répondu Eclipse 2008-11-21 18:11:50