Étrange appel ambigu d’une erreur de fonction surchargée

j’essaie

void function(int y,int w) { printf("int function"); } void function(float y,float w) { printf("float function"); } int main() { function(1.2,2.2); return 0; } 

Je reçois une erreur d’erreur comme ..

 error C2668: 'function' : ambiguous call to overloaded function 

et quand j’essaie d’appeler la function(1.2,2) ou la function(1,2.2) elle function(1,2.2) tant que ” fonction int

Veuillez préciser quand la function(float y,float w) sera appelée?

Regardez le message d’erreur de gcc:

 a.cpp:16: error: call of overloaded 'function(double, double)' is ambiguous a.cpp:3: note: candidates are: void function(int, int) a.cpp:9: note: void function(float, float) 

Un appel à l’une ou l’autre fonction nécessiterait une troncature, raison pour laquelle ni l’une ni l’autre n’est préférée. Je soupçonne que vous voulez vraiment la void function(double y,double w) . N’oubliez pas qu’en C / C ++ , le type à virgule flottante par défaut pour les littéraux et le passage de parameters est double , PAS float .

METTRE À JOUR

Si vous ne voulez vraiment pas changer la signature de la fonction de float à double , vous pouvez toujours utiliser des littéraux qui sont typescripts comme float . Si vous ajoutez le suffixe f aux nombres à virgule flottante , ils seront typescripts float.

Vos exemples seraient alors function(1.2f, 2f) et function(1, 2.2f) .

Qu’est-ce que la surcharge de l’opérateur?

La célèbre FAQ sur la surcharge d’opérateur de Sbi répond de manière très détaillée.

Pourquoi les deux versions de function dans OP sont-elles autorisées?

Notez qu’ils prennent différents types de parameters de fonction ( int et float ) et sont donc qualifiés de surcharges de fonction valides.

Quelle est la résolution de surcharge?

C’est le processus de sélection de la fonction / de l’opérateur le plus approprié par la mise en œuvre du compilateur. Si une fonction viable optimale existe et est unique, la résolution de surcharge réussit et produit le résultat. Sinon, la résolution de surcharge échoue et l’invocation est traitée comme étant mal formée et le compilateur fournit un diagnostic. Le compilateur utilise une séquence de conversion implicite pour trouver la fonction de meilleure correspondance.

C ++ 03 Standard 13.3.3.1 Conversions implicites:

Une séquence de conversion implicite est une séquence de conversions utilisée pour convertir un argument dans un appel de fonction au type du paramètre correspondant à la fonction appelée.

Les séquences de conversion implicites peuvent appartenir à l’une des catégories suivantes:

  • Une séquence de conversion standard (13.3.3.1.1)
  • Une séquence de conversion définie par l’utilisateur (13.3.3.1.2)
  • Une séquence de conversion des points de suspension (13.3.3.1.3)

Notez que chacune d’elles est classée pour déterminer la meilleure fonction viable. La meilleure fonction viable est celle dont tous les parameters ont des séquences de conversion implicites meilleures ou égales par rapport à toutes les autres fonctions viables. La norme détaille chacune d’elles en détail dans les sections respectives. La séquence de conversion standard est pertinente dans ce cas, elle est résumée comme suit:

entrez la description de l'image ici

Avec suffisamment de fond sur la résolution de surcharge.
examinons les exemples de code dans OP:

 function(1.2,2.2); 

Règle importante: 1.2 et 2.2 sont des littéraux et ils sont traités comme un type de données double .

Lors du mappage des séquences de conversion implicites:
Les double types de parameters de fonction avec double type double nécessitent un classement de conversion pour appeler la version float ou int et aucun ne correspond mieux que les autres, ils obtiennent le même score sur le classement de conversion. Le compilateur est incapable de détecter la meilleure correspondance viable et signale une ambiguïté.

 function(1.2,2); 

Lors du mappage de séquence de conversion implicite:
L’un des parameters de fonction 2 correspond exactement à la version de la fonction int , tandis qu’un autre paramètre 1.2 a un rang de conversion . Pour une fonction qui prend float tant que paramètre, les séquences de conversion implicites pour les deux parameters sont de rang de conversion .
Ainsi, la fonction qui prend la version internationale obtient un meilleur score que la version float et est la meilleure correspondance et est appelée.

Comment résoudre les erreurs d’ambiguïté de surcharge?

Si vous ne souhaitez pas que le mappage de séquence de conversion implicite vous déconcerte, fournissez simplement des fonctions et appelez-les de manière à ce que les parameters correspondent exactement . Comme la correspondance exacte est supérieure à toutes les autres, vous avez la garantie que votre fonction souhaitée sera appelée. Dans votre cas, il y a deux façons de le faire:

Solution 1:

Appelez la fonction pour que les parameters correspondent exactement aux fonctions disponibles.

 function(1.2f,2.2f); 

Puisque 1.2f et 2.2f sont traitées comme des types float elles correspondent exactement à la version de la fonction float .

Solution 2:

Indiquez une surcharge de fonction qui correspond exactement au type de paramètre de la fonction appelée.

 function(double, double){} 

Puisque 1.2 et 2.2 sont traités en double la fonction appelée correspond exactement à cette surcharge.

Si vous ne voulez pas (comme expliqué dans la réponse acceptée):

  • utiliser des littéraux float, par exemple 1.2f
  • ou modifier la surcharge de float existante pour double

Vous pouvez append une autre surcharge qui appelle le float:

 void function(double y, double w) { function((float)y, (float)w); } 

Votre code dans main va maintenant appeler la fonction ci-dessus, qui appellera la surcharge float .

La surcharge de fonction dans l’exemple ci-dessus a des appels ambigus parce que le type de retour est identique et que le deuxième argument de l’appel de function est double, ce qui peut être traité comme étant int ou float et le compilateur confond donc avec quelle fonction exécuter.

J’espère que cette aide Ce code est explicite pour toutes les combinaisons

Vous devez envoyer deux float pour appeler une fonction float

 #include #include using namespace std; //when arguments are both int void function(int y,int w) { printf("int function\n"); } //when arguments are both double void function(double y, double w) { printf("double function\n"); } //when arguments are both float void function(float y, float w) { printf("float function\n"); } //when arguments are int and float void function(int y, float x) { printf("int float function\n"); } //when arguments are float and int void function(float y,int w) { printf("float int function\n"); } //when arguments are int and double void function(int y, double w) { printf("int double function\n"); } //when arguments are double and int void function(double y, int x) { printf("double int function\n"); } //when arguments are double and float void function(double y, float x) { printf("double float function\n"); } //when arguments are float and double void function(float y, double x) { printf("float double function\n"); } int main(int argc, char *argv[]) { function(1.2,2.2); function(1.2f,2.2f); function(1,2); function(1.2,2.2f); function(1.2f,2.2); function(1,2.2); function(1,2.2f); function(1.2,2); function(1.2f,2); return 0; } 

Lors de l’envoi d’un type primitif à une fonction en tant qu’argument, si le type primitif que vous envoyez n’est pas exactement le même qu’il demande, vous devez toujours le convertir en type primitif demandé.

 int main() { function(1.3f, 2.4f); function(1.3f, static_cast(2.4)); function(static_cast(1.3), static_cast(2.4)); function(static_cast(1), static_cast(2)); return 0; } 

Par défaut, le nombre décimal est considéré comme double. Si vous voulez que le nombre décimal soit flottant, vous le complétez avec f. Dans votre exemple, lorsque vous appelez function (1.2,2.2), le compilateur considère que les valeurs que vous avez transmises sont doubles et que, par conséquent, la signature de la fonction ne correspond pas.

 function(1.2,1.2) ====> function(double,double) 

Si vous souhaitez conserver la signature de la fonction, vous devez utiliser un suffixe à virgule flottante lorsque vous transmettez un littéral à virgule flottante.

 function(1.2f,1.2f) ====> function(float,float). 

Si vous souhaitez en savoir plus sur les littéraux à virgule flottante, vous pouvez vous référer à

Pourquoi les valeurs en virgule flottante telles que 3.14 sont considérées comme doubles par défaut dans MSVC?

Comme d’autres l’ont dit, vous doublez votre fonction surchargée conçue pour les flotteurs . La surcharge elle-même n’a pas d’erreurs.

Voici l’utilisation correcte de la fonction surchargée (notez le “f” juste après les chiffres):

 function(1.0f, 2.0f); 
 function(1.2,2.2); 

Ces nombres ne sont pas des flotteurs, ils sont des doubles. Donc, ce code dit:

 double p1 = 1.2; double p2 = 2.2; void (*fn)(double /*decltype(p1)*/, double /*decltype(p2)*/) = function; 

Le compilateur recherche maintenant une “fonction” qui prend deux doubles. Il n’y a pas de correspondance exacte. Alors, ensuite, il recherche une fonction qui prend un argument pouvant être converti à partir de doubles. Il y a deux matches.

 function(int, int); function(float, float); 

Vous avez plusieurs options.

  1. Ajouter une surcharge de correspondance exacte.

    fonction d’annulation (double, double) {printf (“double fonction \ n”); }

  2. Utilisez le casting.

    fonction (static_cast (1.2), static_cast (2.2));

  3. Appelez “function” avec des floats au lieu de doubles:

    fonction (1.2f, 2.2f);

Essaye ça

 #include  using namespace std; void print(int i){ cout << i << endl; } void print(float i){ cout << i << endl; } int main(){ print(5); print(5.5f); return 0; } 

En surcharge de fonction lorsque float peut entrer en conflit avec un autre type de données dans d'autres fonctions de même nom, c'est probablement une façon de le surmonter. J'ai essayé cela a fonctionné.

Imaginez simplement comment vos arguments seraient transmis.

S’il est passé en tant que 1.2 et 2.2 à la fonction (int, int), il sera tronqué à 1 et 2.

S’il est passé en tant que 1.2 et 2.2 à (float, float), il sera traité tel quel.

Voici donc où l’ambiguïté s’infiltre.

J’ai trouvé deux façons de résoudre ce problème. Le premier est l’utilisation de littéraux: –

 int main() { function(1.2F,2.2F); return 0; } 

Deuxièmement, et de la façon dont j’aime le faire, cela fonctionne toujours (et peut également être utilisé pour la conversion et la promotion par défaut de C ++). Pour int: –

 int main() { int a=1.2, b=2.2; function(a,b); return 0; } 

Pour Float: –

 int main() { float a=1.2, b=2.2; function(a,b); return 0; } 

Donc, au lieu d’utiliser les chiffres réels. Il est préférable de les déclarer d’abord en tant que type, puis en surcharge!

Voir maintenant, si vous l’envoyez en tant que (1.2,2) or (1,2.2) le compilateur peut simplement l’envoyer à la fonction int et cela fonctionnera. Cependant, pour l’envoyer à la fonction float, le compilateur devrait promouvoir 2 à float. La promotion ne se produit que lorsqu’aucune correspondance n’est trouvée.

Voir: – Informatique avec C ++ Sumita Arora Chapitre: Surcharge fonctionnelle