Files
2025-10-25 03:02:53 +03:00

5.3 KiB

[dcl.ambig.res]

9 Declarations [dcl]

9.3 Declarators [dcl.decl]

9.3.3 Ambiguity resolution [dcl.ambig.res]

1

#

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 an object declaration with a function-style cast as the initializer and a declaration involving a function declarator with a redundant set of parentheses around a parameter name.

Just as for the ambiguities mentioned in [stmt.ambig], the resolution is to consider any construct, such as the potential parameter declaration, that could possibly be a declaration to be a declaration.

However, a construct that can syntactically be a declaration whose outermost declarator would match the grammar of a declarator with a trailing-return-type is a declaration only if it starts with auto.

[Note 1:

A declaration can be explicitly disambiguated by adding parentheses around the argument.

The ambiguity can be avoided by use of copy-initialization or list-initialization syntax, or by use of a non-function-style cast.

— end note]

[Example 1: struct S { S(int);};typedef struct BB { int C[2]; } *B, C;

void foo(double a) { S v(int(a)); // function declaration S w(int()); // function declaration S x((int(a))); // object declaration S y((int)a); // object declaration S z = int(a); // object declaration S a(B()->C); // object declaration S b(auto()->C); // function declaration} — end example]

2

#

An ambiguity can arise from the similarity between a function-style cast and atype-id.

The resolution is that any construct that could possibly be atype-id in its syntactic context shall be considered atype-id.

However, a construct that can syntactically be a type-id whose outermost abstract-declarator would match the grammar of an abstract-declarator with a trailing-return-type is considered a type-id only if it starts with auto.

[Example 2: template struct X {};template struct Y {}; X<int()> a; // type-id X<int(1)> b; // expression (ill-formed) Y<int()> c; // type-id (ill-formed) Y<int(1)> d; // expressionvoid foo(signed char a) {sizeof(int()); // type-id (ill-formed)sizeof(int(a)); // expressionsizeof(int(unsigned(a))); // type-id (ill-formed)(int())+1; // type-id (ill-formed)(int(a))+1; // expression(int(unsigned(a)))+1; // type-id (ill-formed)}typedef struct BB { int C[2]; } *B, C;void g() {sizeof(B()->C[1]); // OK, sizeof(expression)sizeof(auto()->C[1]); // error: sizeof of a function returning an array} — end example]

3

#

Another ambiguity arises in aparameter-declaration-clause when atype-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 thedeclarator-id.

The resolution is to consider thetype-name as asimple-type-specifier rather than adeclarator-id.

[Example 3: 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]