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

77 lines
5.3 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[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.11Ambiguity 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.11Ambiguity 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.1Preamble[dcl.pre]") whose outermost [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") would match the grammar of a [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") with a [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1General[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.2Type 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.2Type names[dcl.name]") in its syntactic context shall be considered a[*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]")[.](#2.sentence-2)
However, a construct that can syntactically be a [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") whose outermost [*abstract-declarator*](dcl.name#nt:abstract-declarator "9.3.2Type names[dcl.name]") would match the grammar of an [*abstract-declarator*](dcl.name#nt:abstract-declarator "9.3.2Type names[dcl.name]") with a [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1General[dcl.decl.general]") is considered a [*type-id*](dcl.name#nt:type-id "9.3.2Type 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.6Functions[dcl.fct]") when a[*type-name*](dcl.type.simple#nt:type-name "9.2.9.3Simple 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.1General[dcl.decl.general]")[.](#3.sentence-2)
The resolution is to consider the[*type-name*](dcl.type.simple#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]") as a[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]") rather than a[*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[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*]