My program was crashing, no debugger readily available, so I spiked it with printfs, narrowed it down to the (lengthy) initializer list, and tried to get it to show which initializer expression causes the crash, by stuffing printf(...),
before each expression, so it looked something like this:
#include <cstdio>
class X
{
public:
int a_;
int b_;
X(int a, int b);
};
X::X(int a, int b) :
a_(printf("Initializing a\n"), a),
b_(printf("Initializing b\n"), b)
{}
int main() {
X x(1,2);
return 0;
}
My reasoning was the comma operator should swallow the return value of printf, execute the following expression, and initialize the property as normal. Instead, I got an error:
hw.cpp: In constructor 'X::X(int, int)':
hw.cpp:12:5: error: expression list treated as compound expression in mem-initializer [-fpermissive]
12 | a_(printf("Initializing a\n"), a),
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hw.cpp:13:5: error: expression list treated as compound expression in mem-initializer [-fpermissive]
13 | b_(printf("Initializing b\n"), b)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I successfully got around it by enclosing the comma operation by extra parentheses a_((printf("Initializing a\n"), a)),
but I'm still a bit baffled what g++ was trying and failing to achieve in place of performing the comma operator as requested. Can someone explain?
C++ syntax for member initializer list includes a comma-separated list, for cases when the member needs several parameters to initialize:
struct small
{
small(int x, int y, int z) {}
};
struct large
{
small part1, part2;
large(): part1(1, 2, 3), part2(22, 33, 44) {}
};
In your example, you have int
, whose constructor has just one argument. But your code looks like it wants to invoke its constructor with 2 arguments. A separate interpretation of your code, the one you want, is invocation with a single argument which contains the comma-operator. If you want to choose it, you must use additional parentheses.
This is not an ambiguity in the grammar — a comma-separated list in that context means constructing with that number of arguments. But I guess the compiler is trying to be extra helpful, so it mentions this (illegal) interpretation of your code.