I think that
(someClass(otherClass(weco), otherClass(weco)))
is being incorrectly parsed as the start of the second production of a cast-expression:
cast-expression:
unary-expression
(
type-id)
cast-expression
Note § 8.2 paragraph 2 (emphasis added):
The ambiguity arising from the similarity between a function-style cast and a type-id can occur in different contexts. The ambiguity appears as a choice between a function-style cast expression and a declaration of a type. The resolution is that any construct that could possibly be a type-id in its syntactic context shall be considered a type-id.
If you consider the full syntactic context of the type-id in cast-expression, it's not possible for ...
in (..);
to match type-id
, because the cast-expression following the )
cannot be empty. However, if you only consider the one-token-lookahead context, where the type-id must be followed by )
, it could be plausible that 8.2(2) applies. I'm not really inclined to believe that the intention of the standard was to only consider one-token lookahead, though.
EDIT Reported as gcc bug 50637. You might want to submit a similar bug report to xlc.
Since gcc 4.7.2 seems to flag the same error as xlc. I played around with gcc a bit, and convinced myself that the problem is that gcc flags the error in the type-id (i.e., two parameters with the same name) before it figures out that the parenthesized expression cannot be a type-id.
Here's an example:
#include <iostream>
#include <utility>
static const int zero = 0;
int main() {
// Consistent with 8.2[2]
// Example 1. Invalid cast.
// Here, 'int(int(zero))' is a type-id, so the compiler must take
// the expression to be a cast of '+3' to a function.
std::cout << (int(int(zero))) + 3 << std::endl;
// Example 2: No error.
// The parenthesized expression cannot be a type-id in this context
std::cout << (int(int(zero))) << std::endl;
// Example 3: Syntax error: zero redefined.
// Here the parenthesized expression could be a type-id, so it must
// be parsed as one, even though the type-id is invalid.
std::cout << (std::pair<int,int>(int(zero), int(zero))) + 3 << std::endl;
// Apparently not consistent with 8.2[2]
// Here the parenthesized expression can't be a type-id, as in example 2.
// However, the type-id triggers a syntax error, presumably before gcc
// figures out that it's not a cast-expression.
std::cout << (std::pair<int,int>(int(zero), int(zero))) << std::endl;
return 0;
}
See it on lws. (Toggle between gcc and clang to see the difference.)
Based on the above analysis that the problem is premature triggering of a type-error, here's one possible workaround:
1) Add an alias for weco:
emptyList& weco_alias = weco;
2) Use one of each:
someClass nuni = (someClass(otherClass(weco), otherClass(weco_alias)));
This works on both gcc 4.7.2 and clang 3.2 (lws).