views:

167

answers:

5

If you see this code,

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) 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?

+7  A: 

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

Justin Niessner
What are the “similar constructs”?
Philipp
@Philipp: Basically, those constructs in which the grammar explicitly describes the meaning of the comma. The above list skips for instance member and friend declarations, which are very similar to variable declarations. Another example would be a temporary object expression such as `Complex(0,1)` which is similar to a function call.
MSalters
+1 for super concise answer.
A: 

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.

Jerry Coffin
+4  A: 

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.

GMan
+6  A: 

From a grammatical point of view the parameters of a function call from 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) );
Charles Bailey
+4  A: 

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.

Johannes Schaub - litb