It seems the current standard draft cannot interpret why two structured binding declaration conflict with each other - c++

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

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.)

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.

Related

why a structured binding does not potentially conflict with a variable

The newest standard has been modified to add the content of P1787. One rule about two declarations that potentially conflict is:
Two declarations potentially conflict if they correspond and cause their shared name to denote different entities ([basic.link]).
I don't know the meaning of wording "different entities" here. Does it mean these entities that has different kinds or mean that they are different entities determined by basic.link#8? The entities have these kinds:
An entity is a value, object, reference, structured binding, function, enumerator, type, class member, bit-field, template, template specialization, namespace, or pack.
Such for a example,
void fun(); //#1
extern int fun; //#2
int main(){}
If the wording "different entities" means the former, then #1 denotes a function and #2 denotes a variable, they're different kind of entities. And such two declaration are in the same scope, Hence they are ill-formed per:
The program is ill-formed if, in any scope, a name is bound to two declarations that potentially conflict and one precedes the other
However, if the differenct entities should be determined by [basic.link#8] instead of determing it according to kind of entities. Then, it also makes sense. Because, 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
they both declare names with module linkage and are attached to the same module, or
they both declare names with external linkage.
Since they're corresponding and have the same target scope, and also bullet 1 or bullet 3 is satisfied. So, #1 and #2 are the same entity. However, they violate the following rule:
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.
So, Regardless of how to understand "different entities", the first example is always ill-formed. These compilers indeed give a right dignosis.
However, consider the second example
#include <iostream>
struct D{
int m;
};
auto [x] = D{0}; //#1
void show(){
std::cout<<&x<<"\n";
}
int main(){
extern int x; //#2
std::cout<<&x<<"\n";
}
GCC prints the same address. Instead, Clang reports a link error.
Similarly, if "different entities" is the former opinion. Then #1 is a structured binding while #2 is a variable. According to this rule:
if the declaration inhabits a block scope S and declares a function ([dcl.fct]) or uses the extern specifier, the declaration shall not be attached to a named module ([module.unit]); its target scope is the innermost enclosing namespace scope, but the name is bound in S.
So, such two declarations has the same target scope. Hence, they should potentially conflict. If "different entities" is determined by [basic.link]. According to [basic.link#8], they are the same entity. However, it also violates
If one declares E to be a variable or function, the other shall declare E as one of the same type.
So, anyhow, the second example should be ill-formed. Why GCC gives the result that such two entity has the same address. Rather, Clang only gives a link error?
In addition, Is it necessary to add a precondition for [basic.link#8], that is, two entities should be first have the same kind?

Can using a lambda in header files violate the ODR?

Can the following be written in a header file:
inline void f () { std::function<void ()> func = [] {}; }
or
class C { std::function<void ()> func = [] {}; C () {} };
I guess in each source file, the lambda's type may be different and therefore the contained type in std::function (target_type's results will differ).
Is this an ODR (One Definition Rule) violation, despite looking like a common pattern and a reasonable thing to do? Does the second sample violate the ODR every time or only if at least one constructor is in a header file?
This boils down to whether or not a lambda's type differs across translation units. If it does, it may affect template argument deduction and potentially cause different functions to be called - in what are meant to be consistent definitions. That would violate the ODR (see below).
However, that isn't intended. In fact, this problem has already been touched on a while ago by core issue 765, which specifically names inline functions with external linkage - such as f:
7.1.2 [dcl.fct.spec] paragraph 4 specifies that local static variables and string literals appearing in the body of an inline function with
external linkage must be the same entities in every translation unit
in the program. Nothing is said, however, about whether local types
are likewise required to be the same.
Although a conforming program could always have determined this by use
of typeid, recent changes to C++ (allowing local types as template
type arguments, lambda expression closure classes) make this question
more pressing.
Notes from the July, 2009 meeting:
The types are intended to be the same.
Now, the resolution incorporated the following wording into [dcl.fct.spec]/4:
A type defined within the body of an extern inline function is the same type in every translation unit.
(NB: MSVC isn't regarding the above wording yet, although it might in the next release).
Lambdas inside such functions' bodies are therefore safe, since the closure type's definition is indeed at block scope ([expr.prim.lambda]/3).
Hence multiple definitions of f were ever well-defined.
This resolution certainly doesn't cover all scenarios, as there are many more kinds of entities with external linkage that can make use of lambdas, function templates in particular - this should be covered by another core issue.
In the meantime, Itanium already contains appropriate rules to ensure that such lambdas' types coincide in more situations, hence Clang and GCC should already mostly behave as intended.
Standardese on why differing closure types are an ODR violation follows. Consider bullet points (6.2) and (6.4) in [basic.def.odr]/6:
There can be more than one definition of […]. Given such an entity named D defined in more than one translation unit, then each definition of D shall consist of the
same sequence of tokens; and
(6.2) - in each definition of D, corresponding names, looked up
according to [basic.lookup], shall refer to an entity defined within
the definition of D, or shall refer to the same entity, after
overload resolution ([over.match]) and after matching of partial
template specialization ([temp.over]), […]; and
(6.4) - in each definition of D, the overloaded operators referred to,
the implicit calls to conversion functions, constructors,
operator new functions and operator delete functions, shall refer to
the same function, or to a function defined within the definition of
D; […]
What this effectively means is that any functions called in the entity's definition shall be the same in all translation units - or have been defined inside its definition, like local classes and their members. I.e. usage of a lambda per se is not problematic, but passing it to function templates clearly is, since these are defined outside the definition.
In your example with C, the closure type is defined within the class (whose scope is the smallest enclosing one). If the closure type differs in two TUs, which the standard may unintentionally imply with the uniqueness of a closure type, the constructor instantiates and calls different specializations of function's constructor template, violating (6.4) in the above quote.
UPDATED
After all I agree with #Columbo answer, but want to add the practical five cents :)
Although the ODR violation sounds dangerous, it's not really a serious problem in this particular case. The lambda classes created in different TUs are equivalent except their typeids. So unless you have to cope with the typeid of a header-defined lambda (or a type depending on the lambda), you are safe.
Now, when the ODR violation is reported as a bug, there is a big chance that it will be fixed in compilers that have the problem e.g. MSVC and probably some other ones which don't follow the Itanium ABI. Note that Itanium ABI conformant compilers (e.g. gcc and clang) are already producing ODR-correct code for header-defined lambdas.

const typedef; in C and C++

What was the original reason behind allowing statements like the following in C and C++?
const typedef;
It doesn't seem to make any practical sense.
Also, you can do this: const; and typedef;
Edit: #AndreyT points out it is not a standard defined behavior. For the full answer, I would like to know about any possible advantages that arose in front of GCC devs when they decided this type of code should be compilable.
This looks like a degenerate form of declaration.
In C declaration is not a statement. It is a declaration. And what you have above is not allowed.
6.7 Declarations
2 A declaration shall declare at least a declarator (other than the
parameters of a function or the members of a structure or union), a
tag, or the members of an enumeration.
In C++ declaration is a statement. But still what you have above is not allowed. From C++03
7 Declarations
3 In a simple-declaration, the optional init-declarator-list can be
omitted only when declaring a class (clause 9) or enumeration (7.2),
that is, when the decl-specifier-seq contains either a
class-specifier, an elaborated type-specifier with a class-key (9.1),
or an enum-specifier.
If some compiler allows this in C or C++ code, it must be a quirk of that compiler. You should direct that question to its authors.
As you probably know, the syntax of C and C++ is not specified by the grammar alone. Doing it by the grammar alone would be too complicated or downright impossible. Some additional restrictions are imposed by the text that accompanies the grammar. Compilers usually treat the grammar itself with respect, but when it comes to those elaborate additional restrictions... many compilers allows some violations to slip through.
I would make an educated guess that this must be a side-effect of the "empty declaration" extension. Since the beginning of times empty declarations were illegal in C and C++. For example, this code has always been illegal
void foo() {}; // In file scope
because it follows function definition with an empty declaration. However, virtually all compilers accepted it, allowing empty declarations as an extension. For the very same reason you could write
;;;; // In file scope
in the middle of the file and have your code compile. What you have in your example is also an empty declaration, into which you added some inconsequential qualifiers and storage-class specifiers.
P.S. Correct me if I'm wrong, but C++11 legalized empty declarations. I'm not sure about C11.

Why is the 'Declare before use' rule not required inside a class? [duplicate]

This question already has answers here:
Do class functions/variables have to be declared before being used?
(5 answers)
Closed 4 years ago.
I'm wondering why the declare-before-use rule of C++ doesn't hold inside a class.
Look at this example:
#ifdef BASE
struct Base {
#endif
struct B;
struct A {
B *b;
A(){ b->foo(); }
};
struct B {
void foo() {}
};
#ifdef BASE
};
#endif
int main( ) { return 0; }
If BASE is defined, the code is valid.
Within A's constructor I can use B::foo, which hasn't been declared yet.
Why does this work and, mostly, why only works inside a class?
Well, to be pedantic there's no "declare before use rule" in C++. There are rules of name lookup, which are pretty complicated, but which can be (and often are) roughly simplified into the generic "declare before use rule" with a number of exceptions. (In a way, the situation is similar to "operator precedence and associativity" rules. While the language specification has no such concepts, we often use them in practice, even though they are not entirely accurate.)
This is actually one of those exceptions. Member function definitions in C++ are specifically and intentionally excluded from that "declare before use rule" in a sense that name lookup from the bodies of these members is performed as if they are defined after the class definition.
The language specification states that in 3.4.1/8 (and footnote 30), although it uses a different wording. It says that during the name lookup from the member function definition, the entire class definition is inspected, not just the portion above the member function definition. Footnote 30 additionally states though that the lookup rules are the same for functions defined inside the class definition or outside the class definition (which is pretty much what I said above).
Your example is a bit non-trivial. It raises the immediate question about member function definitions in nested classes: should they be interpreted as if they are defined after the definition of the most enclosing class? The answer is yes. 3.4.1/8 covers this situation as well.
"Design & Evolution of C++" book describes the reasoning behind these decisions.
That's because member functions are compiled only after the whole class definition has been parsed by the compiler, even when the function definition is written inline, whereas regular functions are compiled immediatedly after being read. The C++ standard requires this behaviour.
I don't know the chapter and verse of the standard on this.
But if you would apply the "declare before use" rule strictly within a class, you would not be able to declare member variables at the bottom of the class declaration either. You would have to declare them first, in order to use them e.g. in a constructor initialization list.
I could imagine the "declare before use" rule has been relaxed a bit within the class declaration to allow for "cleaner" overall layout.
Just guesswork, as I said.
The most stubborn problems in the definition of C++ relate to name lookup: exactly which uses of a name refer to which declarations? Here, I'll describe just one kind of lookup problem: the ones that relate to order dependencies between class member declarations. [...]
Difficulties arise because of conflicts between goals:
We want to be able to do syntax analysis reading the source text once only.
Reordering the members of a class should not change the meaning of the class.
A member function body explicitly written inline should mean the same thing when written out of line.
Names from an outer scope should be usable from an inner scope (in the same way as they are in C).
The rules for name lookup should be independent of what a name refers to.
If all of these hold, the language will be reasonably fast to parse, and users won't have to worry about these rules because the compiler will catch the ambiguous and near ambiguous cases. The current rules come very close to this ideal.
[The Design And Evolution Of C++, section 6.3.1 called Lookup Issues on page 138]

Static Constant Class Members

Consider the following snippet:
struct Foo
{
static const T value = 123; //Where T is some POD-type
};
const T Foo::value; //Is this required?
In this case, does the standard require us to explicitly declare value in a translation unit? It seems I have conflicting information; boost and things like numeric_limits from the STL seem to do this sort of thing just like in my snippet.
OTOH, I remember reading somewhere (albeit a long long time ago) that you're still required to provide a declaration in a translation unit.
If this is the case, what about template specialization? Will each specialization require a declaration?
I'd appreciate your comments as to what the "right way" is.
You have to provide a definition in a translation unit too, in case you use the value variable. That means, if for example you read its value.
The important thing is that the compiler is not required to give a warning or error if you violate that rule. The Standard says "no diagnostic required" for a violation.
In the next C++ Standard version, the rule changed. A variable is not used when it is used as a constant expression. Simply reading value above where the variable is initialized directly in the class means that still no definition is required then.
See the definition of use in section 3.2 One Definition Rule of the Standard and requirement for a definition for static data-members in 9.4.2, paragraph 4 and 5 (in the C++98 Standard. Appears in paragraph 3 and 4 in the n2800 draft of the next Standard).
Correction: The rule already changed for c++03: If the variable appears where a integral constant expression is required, no definition is needed (quoting from an unofficial revisions list for the 2003 update), see resolution for this language defect report:
An expression is potentially evaluated unless it appears where an integral constant expression is required (see 5.19), is the operand of the sizeof operator (5.3.3), or is the operand of the typeid operator and the expression does not designate an lvalue of polymorphic class type (5.2.8)...
Note that even then, many uses are in cases where an integral constant is not required. Cases where one is, is in array dimensions or in template metaprogramming. So strictly speaking (see this report), only the c++1x solution provides really guarantee that in obvious cases also like "s == string::npos" where an integral constant is not required the definition of the static member is not needed, because the next Standard has a different, better wording of 3.2. This is however quite theoretical stuff, since most (all?) compiler don't moan anyway. Thanks for the guy in the comment section for telling me.
To add on to what litb said, from my copy of n2798:
9.4.2
[...]
2 The declaration of a static data member in its class definition is not a definition and
may be of an incomplete type other than cv-qualified void. The definition for a static
data member shall appear in a namespace scope enclosing the member’s class definition. In
the definition at namespace scope, the name of the static data member shall be qualified
by its class name using the :: operator.
You don't have to provide a definition for static integral constant members if you don't use them in some way that requires them to be stored in memory somewhere (e.g. take the address of such a member). See Stroustrup's The C++ Programming Language, section 10.4.6.2.
Edit:
Oops, I just re-read the question, and the question was for some type T. In general you would need to provide a definition, I agree. But if you used something from the int family, you wouldn't necessarily have to (with the caveat above).