77 lines
5.3 KiB
Markdown
77 lines
5.3 KiB
Markdown
[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*]
|