38 votes

Est-ce que gcc ou clang est correct à propos de ce comportement ?

J'ai un petit programme de jouets :

static int value = 0;

int function(int &value=value) {
    return value;
}

int main() {
    function();
}

Compilation avec g++ 7.2 :

g++ -std=c++11 -Wall -Wextra test.cc -o test

Pas de problème.

Compilation avec clang++-3.9 :

clang++-3.9 -std=c++11 -Wall -Wextra test.cc -o test

test.cc:3:25: error: default argument references parameter 'value'
int function(int &value=value) {
                        ^~~~~
test.cc:8:5: error: no matching function for call to 'function'
    function();
    ^~~~~~~~
test.cc:3:5: note: candidate function not viable: requires single argument 'value', but no arguments were provided
int function(int &value=value) {
    ^
2 errors generated.

Kaboom. Qui a raison ?

32voto

R Sahu Points 24027

Je pense que Clang a raison. De pdecl de base.scope :

Le point de déclaration d'un nom se situe immédiatement après son déclarateur complet (Clause [dcl.decl] ) et avant son initialisateur (le cas échéant), à l'exception de ce qui est indiqué ci-dessous. [ Exemple :

int x = 12;{ int x = x; }

Ici, le deuxième x est initialisé avec sa propre valeur (indéterminée). - fin de l'exemple ]

De plus, de dcl.fct.default :

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és avant un argument par défaut sont dans la portée et peuvent cacher les noms des espaces de noms et des membres de la classe.

18voto

Johan Points 2245

Comme l'OP a indiqué que la question portait sur c++11, j'ai vérifié cette version de la norme et dans [basic.lookup.unqual] la sous-clause 11 stipule explicitement que :

Au cours de la recherche d'un nom utilisé comme argument par défaut (8.3.6) dans un clause de déclaration des paramètres d'une fonction ou utilisé dans l'expression d'un mem-initialisateur pour un constructeur (12.6.2), les noms des paramètres de la fonction sont visibles et cachent les noms des entités déclarées dans le bloc, la classe ou l'espace de nom. blocs, classes ou espaces de noms contenant la déclaration de la fonction.

Ainsi, clang est correct.

8voto

NathanOliver Points 10062

Clang est correct ici. D'abord un la portée des paramètres de la fonction est défini comme suit :

Un paramètre de fonction (y compris celui qui apparaît dans un déclarateur lambda) ou une variable prédéfinie locale à une fonction ([dcl.fct.def]) a une portée de paramètre de fonction. La portée potentielle d'un paramètre ou d'une variable prédéfinie locale à une fonction commence à son point de déclaration [...].

et le point de déclaration est défini comme suit

Le point de déclaration d'un nom se situe immédiatement après son déclarant complet et avant son initialisateur (le cas échéant), sauf dans les cas indiqués ci-dessous. [Exemple :

unsigned char x = 12;
{ unsigned char x = x; }

Ici, le deuxième x est initialisé avec sa propre valeur (indéterminée). - fin de l'exemple ]

Alors value devrait être le value que vous venez de déclarer et non celui de l'espace global

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