[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 <class T> struct X {};template <int N> 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](#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*]
