The ambiguity arising from the similarity between a function-style cast and a declaration mentioned in [stmt.ambig] can also occur in the context of a declaration. In that context, the choice is between a function declaration with a redundant set of parentheses around a parameter name and an object declaration with a function-style cast as the initializer. Just as for the ambiguities mentioned in [stmt.ambig], the resolution is to consider any construct that could possibly be a declaration a declaration. [ Note: A declaration can be explicitly disambiguated by a nonfunction-style cast, by an = to indicate initialization or by removing the redundant parentheses around the parameter name. — end note ] [ Example:
struct S { S(int); }; void foo(double a) { S w(int(a)); // function declaration S x(int()); // function declaration S y((int)a); // object declaration S z = int(a); // object declaration }
— end example ]
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.
[ Example:
#include <cstddef> char *p; void *operator new(std::size_t, int); void foo() { const int x = 63; new (int(*p)) int; // new-placement expression new (int(*[x])); // new type-id }
For another example,
template <class T> struct S { T *p; }; S<int()> x; // type-id S<int(1)> y; // expression (ill-formed)
For another example,
void foo() { sizeof(int(1)); // expression sizeof(int()); // type-id (ill-formed) }
For another example,
void foo() { (int(1)); // expression (int())1; // type-id (ill-formed) }
— end example ]
Another ambiguity arises in a parameter-declaration-clause of a function declaration, or in a type-id that is the operand of a sizeof or typeid operator, when a type-name is nested in parentheses. In this case, the choice is between the declaration of a parameter of type pointer to function and the declaration of a parameter with redundant parentheses around the declarator-id. The resolution is to consider the type-name as a simple-type-specifier rather than a declarator-id. [ Example:
class C { }; void f(int(C)) { } // void f(int(*fp)(C c)) { } // not: void f(int C); int g(C); void foo() { f(1); // error: cannot convert 1 to function pointer f(g); // OK }
For another example,
class C { }; void h(int *(C[10])); // void h(int *(*_fp)(C _parm[10])); // not: void h(int *C[10]);
— end example ]