Reputation: 7369
struct A{
int a;
};
struct B{
int b;
};
auto&& [x] = A{}; //#1
auto&& [x] = B{}; //#2
int main(){
}
In this example, all compilers give an error that the x
at #2 conflicts with that introduced at #1. However, IIUC, there's no rule in the post-C++20 working draft standard which can interpret what's the reason.
First, in my opinion, the declaration at #2 and the declaration at #1 declare the same entity. They correspond due to: basic.scope#scope-3
Two declarations correspond if they (re)introduce the same name, both declare constructors, or both declare destructors, unless
[...]
They declare the same entity per basic.link#8
Two declarations of entities declare the same entity if, considering declarations of unnamed types to introduce their names for linkage purposes, if any ([dcl.typedef], [dcl.enum]), they correspond ([basic.scope.scope]), have the same target scope that is not a function or template parameter scope, and either
- they appear in the same translation unit, or
- [...]
So, as far as now, they declare the same entity and they shouldn't be considered as potentially conflict per basic.scope#scope-4
Two declarations potentially conflict if they correspond and cause their shared name to denote different entities([basic.link]). The program is ill-formed if, in any scope, a name is bound to two declarations that potentially conflict and one precedes the other ([basic.lookup]).
Since they denote the same entity, as aforementioned, they do not potentially conflict.
They still do not violate this rule:
basic.link#11
For any two declarations of an entity E:
- If one declares E to be a variable or function, the other shall declare E as one of the same type.
- [...]
Since structured bindings are not mentioned in this list, they do not violate this rule. Similar, they do not violate One-definition rule
No translation unit shall contain more than one definition of any variable, function, class type, enumeration type, template, default argument for a parameter (for a function in a given scope), or default template argument.
At least, according to what the relevant rules say, the two declarations in this example shouldn't result in any program ill-formed. If I don't miss some other rules, Can it be considered as vague in the standard which cannot interpret why two structured binding declarations conflict with each other in this case? This case is more underspecified in the N4861
Upvotes: 4
Views: 153
Reputation: 40053
This is just a missing case in [basic.link]/11: that if one (of the two declarations) declares a structured binding, the program is ill-formed. (One could alternatively merely require that the other also declare a structured binding and then extend the list in [basic.def.odr]/1, but that’s more complicated and suggests that it might be possible to redefine it in another translation unit.)
Upvotes: 4
Reputation: 474436
You are citing text from a working draft of a post-C++20 version of the language. As such, the behavior it describes is not likely implemented by any compiler currently existing. As it is a working draft, it likely contains a number of language defects and/or bugs, so trying to learn from it is not a productive activity.
All of the "correspond" language you cite is adopted from P1787, which is not part of any C++ standard actual compilers implement. As such, compilers are providing you with the C++20 functionality, and under those rules, these clearly conflict.
There may be some defective wording in P1787, but that's expected with complex proposals and working drafts of a standard. File a defect report on it.
Upvotes: 1