开发者

When all does comma operator not act as a comma operator?

开发者 https://www.devze.com 2023-01-05 01:58 出处:网络
If you see this code, class A{ public: A(int a):var(a){} int var开发者_StackOverflow; }; int f(A obj) { return obj.var;

If you see this code,

class A{
public:
    A(int a):var(a){}
    int var开发者_StackOverflow;
};

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) does not compile because the comma acts as a separator here and not as a comma operator.

Where all does a comma not work as a comma operator? Or the other way around?


From a grammatical point of view, the parameters of a function call form an optional expression-list inside parentheses. An expression-list consists of one or more assignment-expression separated by a comma token. A comma can only signify a comma operator where an expression is expected.

The comma operator makes an expression out of an expression, a , and an assignment-expression, but an expression involving a comma operator is not itself an assignment-expression so can't appear in an expression-list except where it's a constituent of something that is an assignment-expression.

For example, you can surround any expression (including one using the comma operator) inside parentheses to from a primary-expression which is an assignment-expression and hence valid in an expression-list.

E.g.

postfix-expression where the expression-list consists of two assignment-expression each of which is an identifier.

f( a, b );

postfix-expression where the expression-list consists of a single assignment-expression which is a primary-expression which is a parenthesized expression using the comma operator.

f( (a, b) );


The use of the comma token as an operator is distinct from its use in function calls and definitions, variable declarations, enum declarations, and similar constructs, where it acts as a separator.

Wikipedia - Comma operator


I did a search over the draft Standard. Basically, in the grammar the -list productions are the ones that have commas in them to separate different items. The following results are C++03 specific. In C++0x, expression-list directly delegates to initializer-list because in C++0x brace lists can occur in function and constructor arguments likewise.

  • expression-list For function/constructor arguments (including functional casts)
  • enumerator-list The list of items of an enumeration
  • init-declarator-list The different names declared in one declaration

    Example:

    int a, b;
    
  • parameter-declaration-list The parameter declaration list (surprise!) of a function
  • initializer-list List similar to expression-list, but can include braced expression lists. Used for aggregate initialization (initializing arrays or structs)
  • member-declarator-list Similar to the init declarator list, but for member declarations in classes.

    Example:

    struct A { int a, b; };
    
  • base-specifier-list List of base-classes of a class.
  • mem-initializer-list List of the initializers for members

    Example:

    struct A { A():a(0), b(0) { } int a; int b; };
    
  • template-parameter-list List of template parameter declarations.
  • template-argument-list List of template arguments passed to a template.
  • type-id-list List of types for exception specifications

    Example:

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

There is an identifier-list for macro parameters too, which i haven't got in that list because it's really part of the preprocessor grammar.


This has to do with the language definition of expressions, which is quite complex.

f(1, 2) is a function call expression with two parameters. Contrarily, f((1, 2)) is a function call expression with one parameter, which is the sub-expression 1, 2, which will evaluate to 2.


A comma operator always acts as a comma operator, but a comma doesn't always signify a comma operator -- sometimes it's just punctuation.

As to when it's punctuation, the simple answer is "when the standard says so." Going through all the situations where the standard says so gives a much longer answer -- but one that's unlikely to be much more useful, because (for one example) it has to deal with a number of corner cases most people don't care much about.

0

精彩评论

暂无评论...
验证码 换一张
取 消