35 votes

Est-il légal d'utiliser un paramètre de fonction précédent pour en déclarer un nouveau ?

Le code suivant se compile proprement avec GCC :

void func(int arg1, decltype(arg1) arg2)
{
    (void)arg2;
}
int main(){}

J'ai utilisé cette commande pour compiler :

g++ -std=c++14 test.cpp -o test -pedantic-errors -Wall -Wextra

Mais une telle utilisation d'un paramètre au milieu de la déclaration de la fonction semble bizarre. Est-ce réellement valable dans le C++ standard, ou est-ce une extension de GCC ?

22voto

Galik Points 522

C'est bien. Le site ISO C++11 Standard donne même votre situation en exemple.

Premièrement, le paramètre est dans le champ d'application :

3.3.3 Portée du bloc [ basic.scope.local ]

2 La portée potentielle d'un nom de paramètre de fonction (y compris celui apparaissant dans un déclarateur lambda) ou d'une variable prédéfinie locale à une fonction dans une définition de fonction (8.4) commence à son point de déclaration. une variable prédéfinie locale à une fonction dans une définition de fonction (8.4) commence à son point de déclaration.

Un exemple peut être trouvé ici :

8.3.5 Fonctions [ dcl.fct ]

5 [ Note : Cette transformation n'affecte pas les types des paramètres. Par exemple, int(*)(const int p, decltype(p)*) et int(*)(int, const int*) sont des types identiques. - note de fin ]

11voto

Barry Points 45207

Oui, c'est légal. Il s'agit essentiellement d'une question de portée. De [basic.scope.block] :

La portée potentielle d'un nom de paramètre de fonction (y compris un nom apparaissant dans une balise Déclarateur lambda ) ou d'une variable prédéfinie locale à une fonction dans une définition de fonction (8.4) commence à son point de déclaration.

Le champ d'application de la arg1 commence ici :

void func(int arg1, decltype(arg1) arg2)
------------------^

Par conséquent, arg1 est dans le champ d'application de la déclaration de arg2 . Je pense que c'est suffisant.

La règle d'exclusion de la défaillance arg2 a arg1 est séparé ce qui pour moi suggère que arg1 était dans le champ d'application et devait être explicitement refusé.

6voto

NathanOliver Points 10062

Si nous regardons dans N3979 [dcl.fct.default] nous avons

Les arguments par défaut sont évalués à chaque fois que la fonction est appelée. L'ordre d'évaluation des arguments de la fonction n'est pas spécifié. Par conséquent, les paramètres d'une fonction ne doivent pas être utilisés dans un argument par défaut, même s'ils ne sont pas évalués. Les paramètres d'une fonction déclarée avant un argument par défaut sont dans la portée et peuvent masquer les noms des espaces de noms et des membres de la classe. . [ Exemple :

int a;
int f(int a, int b = a);              // error: parameter a
                                      // used as default argument
typedef int I;
int g(float I, int b = I(2));         // error: parameter I found
int h(int a, int b = sizeof(a));      // error, parameter a used
                                      // in default argument

[...]

C'est moi qui souligne

Ainsi, dans l'exemple a est connu lorsque nous arrivons à b et il cache le a de la portée de l'appelant. Cela m'amène à penser que chaque paramètre de fonction est connu avant chaque paramètre suivant. Cela signifie que vous devriez être en mesure d'utiliser son type. Vous ne pouvez pas utiliser sa valeur - car l'ordre d'évaluation des valeurs n'est pas spécifié - mais les noms devraient être introduits dans l'ordre de gauche à droite.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X