C++ syntax is so weird it even manages to be ambiguous. Actually, forget I said that. In their wisdom, The Designers decided to disambiguate everything. So that given 2 possible parses of the same construct, the compiler is obligated to choose what looks like the wrong one.

Here's an example, familiar to many who've tried to initialise STL containers from iterators returned by functions. But it's so simple, we won't even bother with STL.

class A{};              // A() will return an object
                        // of type A
class B {
  public:
    B(A) {};            // Construct a B by passing it an A
};

int main()
{
  A a;                  // OK; a is an A
  B b(a);               // OK; b is constructed using a
  B c(A());             // OK?  (thinks: construct c
                        // from anonymous A object)
  B d = b;              // OK; construct d from b
  B e = c;              // NOT OK!!!!!
}
Try this code; it will fail, claiming it cannot initialise e from c; it has the wrong type. Why? Didn't we define c to have type B, initialising it with a temporary object of type A which we created expressly for that purpose?

Here's another interpretation of the line B c(A());: c is a function taking an unnamed pointer to a function taking no arguments ("()") and returning an A, and returning a B.

Aware of the ambiguity, the C++ standard says that if you can parse something as a declaration (not a definition), you have to. So the compiler chooses to think of c as a (declared, not defined, but who knows about other translation units...) function rather than as a B. And everything's still legal, so you only get the error when you try to create e from c. The error is reported at the wrong spot.

The solution? Make the definition not look like a function declaration. By adding brackets: B c((A()));.

Herb Sutter actually explains this in his books. The horrible kluge of adding brackets is the "correct" officially sanctioned solution!

Log in or register to write something here or to contact authors.