2010-06-27 16 views
8

Si vous voyez ce code,Lorsque tout l'opérateur de virgule n'agit pas comme un opérateur de virgule?

class A{ 
public: 
    A(int a):var(a){} 
    int var; 
}; 

int f(A obj) { 
    return obj.var; 
} 

int main() { 
    //std::cout<<f(23); // output: 23 
    std::cout<<f(23, 23); // error: too many arguments to function 'int f(A)' 
    return 0; 
} 

f(23, 23) ne compile pas parce que les actes de virgule comme séparateur ici et non comme un opérateur virgule.

Où tout fait une virgule pas fonctionne comme un opérateur de virgule? Ou l'inverse?

Répondre

11

D'un point de vue grammatical, les paramètres d'un appel de fonction forment un en option expression liste entre parenthèses. Une liste d'expressions consiste en une ou plusieurs expressions d'affectation séparées par un jeton de virgule. Une virgule peut seulement signifier un opérateur de virgule où une expression est attendue.

L'opérateur virgule fait une expression sur une expression, un , et une cession d'expression, mais une expression impliquant un opérateur virgule n'est pas lui-même une expression d'affectation donc peut » t apparaissent dans une liste d'expressions sauf si c'est un constituant de quelque chose qui est une expression d'affectation .

Par exemple, vous pouvez entourer toute expression (dont un en utilisant l'opérateur virgule) à l'intérieur entre parenthèses à partir d'une primaire expression qui est une mission d'expression et donc valable dans une expression liste .

E.g.

postfixe-expression où l'expression liste se compose de deux-expression d'affectation dont chacun est un identificateur .

f(a, b); 

postfixe-expression où l'expression liste consiste en un seul -expression d'affectation qui est un -expression primaire qui est un entre parenthèses expression en utilisant l'opérateur virgule.

f((a, b)); 
8

L'utilisation du jeton de la virgule comme un opérateur est distinct de son utilisation dans appels de fonction et les définitions, déclarations de variables, enum déclarations et constructions similaires, où il agit comme un séparateur.

Wikipedia - Comma operator

+4

Quelles sont les "constructions similaires"? – Philipp

+0

@Philipp: Fondamentalement, ces constructions dans lesquelles la grammaire décrit explicitement la signification de la virgule. La liste ci-dessus ignore les déclarations de membres et d'amis, qui sont très similaires aux déclarations de variables. Un autre exemple serait une expression d'objet temporaire telle que 'Complex (0,1)' qui est similaire à un appel de fonction. – MSalters

+0

+1 pour une réponse super concise. – stinky472

1

Un opérateur virgule agit toujours comme un opérateur virgule, mais une virgule ne signifie pas toujours un opérateur virgule - parfois, il est juste la ponctuation. Quant à savoir quand il s'agit de ponctuation, la réponse simple est "quand la norme le dit." Traverser toutes les situations où la norme le dit donne une réponse beaucoup plus longue - mais qui est peu susceptible d'être beaucoup plus utile, parce que (par exemple) il doit faire face à un certain nombre de cas, la plupart des gens s'en foutent sur.

7

Cela a à voir avec la définition du langage des expressions, ce qui est assez complexe.

f(1, 2) est une expression d'appel de fonction avec deux paramètres. Au contraire, f((1, 2)) est une expression d'appel de fonction avec un paramètre, qui est le sous-expression 1, 2, qui évaluera à 2.

+0

Parce que la virgule est un opérateur ici! Le résultat de l'expression la plus à droite est renvoyé. Juste pour clarification à tout lecteur –

8

J'ai effectué une recherche sur le projet de norme. Fondamentalement, dans la grammaire les productions -list sont celles qui ont des virgules en eux pour séparer les différents articles. Les résultats suivants sont spécifiques à C++ 03. En C++ 0x, expression-liste délègue directement à initializer-list car en C++ 0x les listes de croisements peuvent se produire dans les arguments de fonction et de constructeur de même.

  • expression liste Pour fonction/arguments du constructeur (y compris les moulages fonctionnels)
  • énumérateur-list La liste des éléments d'une énumération
  • init-declarator-list Les différents noms déclarés dans une déclaration

    Exemple:

    int a, b; 
    
  • paramètre-déclaration de liste La liste de déclarations de paramètres (! Surprise) d'une fonction
  • initialiseur liste Liste semblable à l'expression liste, mais peut inclure des listes d'expressions entretenues. Utilisé pour initialisation globale ( de tableaux ou d'initialisation struct)
  • -membre declarator liste similaires à la liste des declarator init, mais pour déclarations de membres dans les classes.

    Exemple:

    struct A { int a, b; }; 
    
  • base spécificateur listeListe des classes de base d'une classe.
  • mem-initialiseur liste Liste des initializers pour membres

    Exemple:

    struct A { A():a(0), b(0) { } int a; int b; }; 
    
  • modèle paramètres liste Liste des paramètre de modèle déclarations.
  • template-argument-list Liste des arguments de modèle passés à un modèle.
  • type id-liste Liste des types de spécifications d'exception

    Exemple:

    void f() throw(int, bool) { } 
    

Il y a un identifiant listepour les paramètres macro aussi, que je ne figure pas dans cette liste, car elle fait vraiment partie de la grammaire du préprocesseur.