Skip to main content
The comma operator (,) is a binary operator that evaluates its left operand, discards the resulting value, and then evaluates its right operand, returning the type and value of the right operand. It enforces strict left-to-right evaluation and establishes a sequenced-before relationship (a sequence point) between the two expressions.

Mechanics and Evaluation Rules

  1. Sequencing: expression1 is evaluated first. All side effects associated with expression1 are guaranteed to be fully complete before the evaluation of expression2 begins.
  2. Value Category: The overall result of the comma expression takes the value and type of expression2. The value category of the result strictly matches the value category of expression2:
    • If expression2 is an lvalue, the result is an lvalue.
    • If expression2 is an xvalue (in C++11 and later), the result is an xvalue.
    • If expression2 is a prvalue (pure rvalue), the result is a prvalue.
  3. Precedence: The comma operator has the lowest precedence of all C++ operators. Because of this, it binds less tightly than assignment, requiring explicit grouping via parentheses when capturing its result.

Operator vs. Separator

The comma token serves a dual purpose in C++ syntax. It is critical to distinguish the comma operator from the comma separator. The comma acts strictly as a syntactic separator (not an operator) in the following contexts:
  • Function argument lists: void func(int x, int y); or func(a, b);
  • Variable declarations: int x = 5, y = 10;
  • Initializer lists: int arr[] = {1, 2, 3};
  • Base class specifier lists and member initializer lists.
  • Template parameter lists and arguments.
In these separator contexts, the strict left-to-right evaluation guarantee of the comma operator does not apply. To force the compiler to interpret a comma as an operator within a separator context, the expression must be enclosed in parentheses:

Overloading

The comma operator can be overloaded for user-defined types by defining operator,. To maintain correct semantics and avoid compilation errors or incorrect behavior (such as the inability to call non-const methods on the result), the return type’s constness and reference type must safely match the right-hand operand. Crucially, the constness of the left-hand operand should not dictate the constness of the returned right-hand operand. If implemented as member functions, both overloads must be marked const.
Historical Context on Sequencing: Prior to C++17, overloading the comma operator was highly discouraged because the overloaded version was treated as a standard function call. This meant the strict left-to-right evaluation order and the sequence point between operands were lost, leaving the evaluation of the arguments unsequenced relative to each other (meaning their evaluation could interleave). As of C++17, the evaluation order rules were revised so that overloaded comma operators retain the exact same strict left-to-right sequencing guarantees as the built-in comma operator.
Tired of Poor C++ Skills? Fix That With Deep Grasping!Learn More