While the name of a structure must be unique in the set of structures within a namespace, such a name can be "shared" with variables and functions. For example, the following code compiles just fine:
// Code 1
struct h{};
int h{ 8 };
Similarly, there is no collision in:
// Code 2
struct h{};
void h(){}
1) What was the reasoning to allow that name sharing?
Moreover, if we throw templates into the mix, we have some strange situations. The code
// Code 3
template< class H > void h(){}
struct h{};
template< class H > struct j{};
void j(){}
does compile; but the following code fails:
// Code 4
struct h{};
template< class H > void h(){}
void j(){}
template< class H > struct j{};
2) Why the reasoning that allowed code 2 was not good enough to allow code 4? I am not asking about the rules in the standard. I am asking about the reason behind those rules.
It is important to note that self-referential structs require a name for the struct, or a forward-declared typedef.
A struct in the C programming language (and many derivatives) is a composite data type (or record) declaration that defines a physically grouped list of variables under one name in a block of memory, allowing the different variables to be accessed via a single pointer or by the struct declared name which returns the ...
definition: You can declare a type as a class , struct or union and then use a different one for the definition. Multiple definitions shouldn't compile; multiple declarations however is just fine.
Yes, that is perfectly fine.
1) What was the reasoning to allow that name sharing?
According to "The Design and Evolution of C++", by Bjarne Stroustrup, section 2.8.2 "Structure Tags vs. Type Names", this feature was introduced to maintain compatibility with C. The C language requires the use of the struct
keyword to name a structure (no keyword is required to name a typedef). You can then use the same identifier to declare a structure and either a function or a variable:
struct X { int m; };
void X(void);
X(); // call X
struct X x; // create a new object of type X
A significant syntactic simplification for the benefit of users was introduced into C++ at the cost of some extra work to implementers and some C compatibility problems. [...] In the context of C with Classes [dyp: the predecessor of C++], this had annoyed me for some time because it made user-defined types second-class citizens syntactically.
[...]
The real need to address this particular issue came from the fact that some standard UNIX header files, notably,
stat.h
, rely on astruct
and a variable or function having the same name.-- D&E 2.8.2
2) Why the reasoning that allowed code 2 was not good enough to allow code 4?
I'll first quote the C++11 Standard:
A class template shall not have the same name as any other template, class, function, variable, enumeration, enumerator, namespace, or type in the same scope (3.3), except as specified in (14.5.5 [dyp: class template partial specialization]). Except that a function template can be overloaded either by (non-template) functions with the same name or by other function templates with the same name (14.8.3 [dyp: this refers to overloading]), a template name declared in namespace scope or in class scope shall be unique in that scope.
-- C++11 International Standard [temp]p5
According to my interpretation of this passage, codes 3 and 4 are both illegal. clang++ rejects them, but accepts the first part of code 3:
template< class H > void h(){}
struct h{};
Which, according to [temp]p5, should be illegal as well.
Considering all these examples (3, 4, and the beginning of 3) as illegal, I think the rationale is that you don't need the compatibility exception in those cases: C has no templates.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With