0
votes

Pourquoi les paramètres par défaut ne fonctionnent pas aux côtés d'un pack de paramètres?

à cause de 8.3.6 ([dcl.fct.default] ) / 4 ,

Dans une déclaration de fonction donnée, chaque paramètre postérieur à un paramètre avec un argument par défaut doit avoir un argument par défaut fourni dans cette déclaration ou une déclaration précédente ou doit être un pack de paramètres de fonction.

Les éléments suivants doivent compiler: xxx

mais il ne compile pas en raison de foo ("str3") qui confond le compilateur. Il se plaint qu'il n'y a pas de fonction correspondante pour appeler à FOO (Const Char *) et qu'il ne peut pas convertir "STR3" (type const char * ) Pour taper int .

Je comprends que l'on peut contourner ce problème en recourant à la surcharge de fonction ou en utilisant le paramètre nommé Idiom (cf. where pour placer le paramètre de valeur par défaut dans une fonction de longueur variable en C ++? et Arguments par défaut et fonctions variadiques ). Cependant, j'aimerais savoir si le compilateur est juste stupide ou s'il y a une raison réelle pour laquelle le comportement prévu dans l'exemple de code ci-dessus n'est pas mis en œuvre. En d'autres termes, pourquoi le compilateur se plaignait-il même si j'instimise explicitement la fonction comme FOO (int, const char *) ? C'est comme si l'instanciation explicite ignore simplement la valeur du paramètre par défaut. Pourquoi?


3 commentaires

Le passage que vous avez cité s'applique uniquement à la déclaration et non à l'appel de la fonction. La déclaration de fonction devrait donc effectivement compiler (et elle le fait), mais le dernier appel ne le fait pas (et il n'y a aucune raison pour laquelle il devrait). En outre, vous n'effectuez pas une instanciation explicite nulle part. Enfin, l'ajout d'un pack de paramètres ne signifie pas que vous devez ignorer les exigences de position des arguments optionnels ...


@Maxlanghof Oui, le code ci-dessus n'a pas d'instanciation explicite. Mais j'ai essayé la même chose avec ladite instanciation explicite. Cela ne compile pas. Compte tenu du fait qu'il ne compilait pas non plus si je mettrais le paramètre par défaut à droite au paramètre Pack, il me semble que le concept de paramètre par défaut dans une fonction variable n'existe pas du tout. Est-ce que c'est ça?


Bien sûr qu'il existe. Vos deux premiers appels de fonction démontrent que cela fonctionne parfaitement bien. Vous pouvez réellement mettre deux choses optionnelles (le paramètre facultatif et un paquet de paramètres éventuellement vide) dans la même fonction, mais cela ne vous libère pas de contraintes concernant la position des paramètres. Si vos arguments de fonction commencent par un paramètre facultatif que vous devez ne fournir aucun paramètre ou vous devez fournir une valeur pour le paramètre facultatif. Si les arguments ultérieurs sont variadiques ou optionnels changent rien à ce sujet.


3 Réponses :


5
votes

Les paramètres avec défaut sont toujours en position de position. Votre exemple est le même que

void foo(int i=8, const char * c="hello world")
{
    std::cout << "Default param \t= " << i << "\n";
    std::cout << "Additional param \t= " << c << "\n";
}

int main()
{
    foo();                  // 8 "hello world"
    foo(1, "str1");         // 1 "str1"
    foo("str3");            // ERROR: parameter mismatch

    return 0;
}


0 commentaires

3
votes

Cela ne fonctionne pas pour les mêmes raisons pour lesquelles cela ne fonctionnera pas: xxx

Si vous lisez l'erreur, vous verrez que le compilateur ne peut pas convertir un littéral à chaîne en un int . Et ceci est vrai, le premier paramètre est un INT, et vous l'avez envoyé un littéral à chaîne.

Les paramètres ne peuvent pas être rebondés à une autre position, peu importe s'il y a un argument par défaut ou non.


0 commentaires

5
votes

La norme que vous citez est simplement de dire qu'il est légal de former xxx

lorsque vous l'appelez, vous devez toujours passer un int comme premier Paramètre Sinon, la fonction ne sera pas prise en compte lors de la résolution de la surcharge. Lorsque vous faites xxx

le compilateur va chercher n'importe quelle fonction foo qui prend un const char * ou un Const Char (&) [5] Comme c'est le seul paramètre. Cela signifie que votre fonction est complète ignorée car elle attend et int pour le premier paramètre ou aucun paramètre du tout.


2 commentaires

Est le point de la légalité de cette déclaration uniquement pour permettre aux appels à foo () ? C'est tout ce qu'on peut en dire? Merci.


@Nanashinogombe à peu près. Sans cette exemption, il serait illégal de déclarer Void FOO (int I = 8, TS ... args) Étant donné que tous les arguments après le premier argument par défaut doivent également être défaillants et il n'y a aucun moyen fournir une valeur par défaut pour un pack de paramètres.