8 Declarators [dcl.decl]

8.2 Ambiguity resolution [dcl.ambig.res]

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 ]