[dcl.ambig.res] # 9 Declarations [[dcl]](./#dcl) ## 9.3 Declarators [[dcl.decl]](dcl.decl#dcl.ambig.res) ### 9.3.3 Ambiguity resolution [dcl.ambig.res] [1](#1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2657) The ambiguity arising from the similarity between a function-style cast and a declaration mentioned in [[stmt.ambig]](stmt.ambig "8.11 Ambiguity resolution") can also occur in the context of a declaration[.](#1.sentence-1) 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[.](#1.sentence-2) Just as for the ambiguities mentioned in [[stmt.ambig]](stmt.ambig "8.11 Ambiguity resolution"), the resolution is to consider any construct, such as the potential parameter declaration, that could possibly be a declaration to be a declaration[.](#1.sentence-3) However, a construct that can syntactically be a [*declaration*](dcl.pre#nt:declaration "9.1 Preamble [dcl.pre]") whose outermost [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") would match the grammar of a [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") with a [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [dcl.decl.general]") is a declaration only if it starts with auto[.](#1.sentence-4) [*Note [1](#note-1)*: A declaration can be explicitly disambiguated by adding parentheses around the argument[.](#1.sentence-5) The ambiguity can be avoided by use of copy-initialization or list-initialization syntax, or by use of a non-function-style cast[.](#1.sentence-6) — *end note*] [*Example [1](#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](#2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2700) An ambiguity can arise from the similarity between a function-style cast and a[*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]")[.](#2.sentence-1) The resolution is that any construct that could possibly be a[*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") in its syntactic context shall be considered a[*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]")[.](#2.sentence-2) However, a construct that can syntactically be a [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") whose outermost [*abstract-declarator*](dcl.name#nt:abstract-declarator "9.3.2 Type names [dcl.name]") would match the grammar of an [*abstract-declarator*](dcl.name#nt:abstract-declarator "9.3.2 Type names [dcl.name]") with a [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [dcl.decl.general]") is considered a [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") only if it starts with auto[.](#2.sentence-3) [*Example [2](#example-2)*: template struct X {};template struct Y {}; X a; // type-id X b; // expression (ill-formed) Y c; // type-id (ill-formed) Y 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](#3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2740) Another ambiguity arises in a[*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") when a[*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]") is nested in parentheses[.](#3.sentence-1) 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*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]")[.](#3.sentence-2) The resolution is to consider the[*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]") as a[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") rather than a[*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]")[.](#3.sentence-3) [*Example [3](#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*]