Init
This commit is contained in:
76
cppdraft/dcl/ambig/res.md
Normal file
76
cppdraft/dcl/ambig/res.md
Normal file
@@ -0,0 +1,76 @@
|
||||
[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*]
|
||||
Reference in New Issue
Block a user