According to this link
A point from C++0x draft : n3290
Shall this program is correct ?
EX:
namespace X {};
enum Foo
{
X = 0, #1
Y,
Z = X // X refers to the enum, not the type
};
Iam getting error while execution this program like // #1 'X' redeclared as different kind of symbol
But in the above statement link ...namespace scopes containing the enum-specifier. ...etc
please clarify my doubt.
Otherwise Please any one give me an example that proves the above statement(in link) with namespace
There is a difference in that the original question had a struct X instead of namespace X. The namespace name is visible in this scope, and so is Foo::X as enum names "leak" into the surrounding namespace. That creates a conflict.
In C (and therefore also in C++) the name of a struct/class/union is in a separate "tag namespace" (a C term with a different meaning) which allows us to declare another item using the same name in the same scope:
Difference between 'struct' and 'typedef struct' in C++?
The program is illegal. An enum does not introduce a separate scope
(unless you are using C++11 and add class to it), both the
namespace X and the enumeration constant X are in the same scope.
There are only two cases where the same name can be defined more than
once in the same scope: overloaded functions, and one class name. The
special case for the class name is purely for C compatibility, so that
C API's with functions like:
struct stat { ... };
int stat(const char* path, struct stat* buf);
wouldn't break. If both a class name and another name are present, the
other name has precedence, unless preceded by a class keyword.
Related
This may be a stupid question.
I notice that we use scope resolution operator :: for both a namespace and a static member function.
1)
std::printf("foo");
2)
MyClass::foo();
Here are my questions:
1. How could a C++ compiler differentiate them?
2. What is the process of a C++ compiler when it sees a scope resolution operator?
The gory details are in 3.4.3 Qualified name lookup of the C++ spec (with 3.3.1 Declarative regions and scopes and 5.1.1 (Primary expressions) General also providing some useful information.)
To boil it down, though, both namespaces and classes are "declarative regions", so in your example, std::cout refers to the name cout in the declarative region named std, and MyClass::foo refers to the name foo in the declarative region named MyClass. As far as the :: operator is concerned, namespaces and classes are the "same sort of thing".
In addition, because names must be unique within a declarative region (including the global namespace), the following code is invalid:
//invalid code - does not compile
namespace test { int x; }
class test { static int x; };
In other words, there is no ambiguity between test::x referring to the x in the namespace or the x in the class.
I wrote following simple program & compiled it on gcc compiler
#include <stdio.h>
typedef int i;
void foo()
{
struct i {i i;} i;
i.i = 3;
printf("%i\n", i.i);
}
int main() { foo(); }
It compiles & runs fine in C.(See live demo here) But it fails in compilation in C++. C++ compiler gives following error messages.
prog.cc: In function 'void foo()':
prog.cc:5:17: error: field 'i' has incomplete type 'foo()::i'
struct i {i i;} i;
^
prog.cc:5:12: note: definition of 'struct foo()::i' is not complete until the closing brace
struct i {i i;} i;
See live demo here
I couldn't find rules regarding this in C & C++ standards. Why it compiles fine in C but not in C++ ? What does the standard says about this ? I very well know that C & C++ are different languages having different rules but I am curious to know about exact rules.
The difference between C and C++ is the following. In C the data member i is considered as having type int because if you wanted that it had type struct i then you have to write struct i i specifying the keyword struct before i.
Structure tags are in their own namespace compared with the namespace of other variables.
According to the C Standard (6.2.3 Name spaces of identifiers)
1 If more than one declaration of a particular identifier is visible
at any point in a translation unit, the syntactic context
disambiguates uses that refer to different entities. Thus, there are
separate name spaces for various categories of identifiers, as
follows:
— label names (disambiguated by the syntax of the label declaration
and use);
— the tags of structures, unions, and enumerations (disambiguated by
following any32) of the keywords struct, union, or enum);
— the members of structures or unions; each structure or union has a
separate name space for its members (disambiguated by the type of the
expression used to access the member via the . or -> operator);
— all other identifiers, called ordinary identifiers (declared in
ordinary declarators or as enumeration constants).
As for C++ then inside the structure definition the name of the structure hides the name of the typedef and the compiler issues the error. In C++ there is separate class scope.
For example in C++ (3.4 Name lookup) there is written
3 The injected-class-name of a class (Clause 9) is also considered
to be a member of that class for the purposes of name hiding and
lookup.
and (3.4.1 Unqualified name lookup)
7 A name used in the definition of a class X outside of a member
function body or nested class definition29 shall be declared in one of
the following ways: — before its use in class X or be a member of
a base class of X (10.2), or ...
Thus the injected name of the class hides the typedef name within the class definition.
Take into account that outside the class definition the name of the class can be hidden by the same name of an object. Thus if you want to declare an object of the class in that scope you have to use its elaborated name like
int i;
struct i {};
//...
struct i obj;
This is my second investigation about structure declaration in C++. (The first is here) But now I came across this post. Specifically I am not sure why this is perfectly fine in C but not in C++.
typedef struct{
int one;
int two;
}myStruct;
struct myStruct; //forward declaration fails
void blah(myStruct* pStruct);
The code above compiles fine on my Ubuntu box with GCC. I reason that it is because the first myStruct lives in the normal namespace where function, variable names live. The second myStruct lives in the Tag namespace. When compiler sees myStruct* in the function prototype, it searches in both namespaces and found myStruct in the normal namspace and that name happen to be a typedef name, so it can be a valid type specifier. The second myStruct can be defined later as whatever the programmer wants to be. There won't be any confusion/collision with the first unnamed myStruct since the programmer has to use struct myStruct to refer to the second one.
But in C++, according to the discussion found in the linked question, my understanding is that the first typedef myStruct lives in the normal namespace as usual. The second myStruct also lives in
the normal namespace(no specific tag namespace in C++?) but can be overshadowed by other identifiers. So my question is why wouldn't the first myStruct which is in the same namespace as the second myStruct shadow the second myStruct?
In a more general sense, other than explicit namespaces introduced by the programmer using the namespace facility provided by the C++ language, are there any pre-defined namespaces disambiguating the use of identifiers (including tags, labels, typedef names, object/functino identifiers) like in C? (C has 4 namespaces pre-defined found in my first investigation). Can I find these in the C++ standard stating where these names belong?
EDIT: It seems I didn't ask the question clear enough. All I want to know is
1) Which namespaces (if there are such defined in the language) do Lables, typedef names, tag names of struct/union/enum, normal function, normal variable/object name belong? (If I missed any other kinds of name, please add.)
2) Why can normal function name, normal variable name shadow tag names, while tag names can NOT.
3) If there is any clauses in C++ that specify the name spaces like in C (Section 6.2.1)
In C++, you cannot use struct myStruct to refer to a tagless structure which has been typedefed. And you cannot define a different struct myStruct, because the name collides with the typedef name.
If you add the tag, then both struct myStruct and myStruct alone will refer to the type, in both C and C++:
typedef struct myStruct {
int one;
int two;
} myStruct;
Here there is no collision in C++ because the name resolves to just one type, and this is specifically allowed by a special rule. C++ Standard section 7.1.3 includes the following rules:
In a given non-class scope, a typedef specifier can be used to redefine the name of any type declared in that scope to refer to the type to which it already refers.
If a typedef specifier is used to redefine in a given scope an entity that can be referenced using an elaborated-type-specifier, the entity can continue to be referenced by an elaborated-type-specifier or as an enumeration or class name in an enumeration or class definition respectively.
In a given scope, a typedef specifier shall not be used to redefine the name of any type declared in that scope to refer to a different type.
Similarly, in a given scope, a class or enumeration shall not be declared with the same name as a typedef-name that is declared in that scope and refers to a type other than the class or enumeration itself.
[ Note: A typedef-name that names a class type, or a cv-qualified version thereof, is also a class-name (9.1). If a typedef-name is used to identify the subject of an elaborated-type-specifier (7.1.6.3), a class definition (Clause 9), a constructor declaration (12.1), or a destructor declaration (12.4), the program is ill-formed.
— end note ]
$10.2/4- "[ Note: Looking up a name in
an elaborated-type-specifier (3.4.4)
or base-specifier (Clause 10), for
instance, ignores all nontype
declarations, while looking up a name
in a nested-name-specifier (3.4.3)
ignores function, variable, and
enumerator declarations."
I have found this statement to be very confusing in this section while describing about name lookup.
void S(){}
struct S{
S(){cout << 1;}
void f(){}
static const int x = 0;
};
int main(){
struct S *p = new struct ::S; // here ::S refers to type
p->::S::f();
S::x; // base specifier, ignores the function declaration 'S'
::S(); // nested name specifier, ignores the struct declaration 'S'.
delete p;
}
My questions:
Is my understanding of the rules correct?
Why ::S on the line doing new treated automatically to mean struct S, whereas in the last line ::S means the functions S in the global namespace.
Does this point to an ambiguity in the documentation, or is it yet another day for me to stay away from C++ Standard document?
Q1: I think so.
Q2: Compatibility with C. When you declare a struct in C, the tag name is just that, a tag name. To be able to use it in a standalone way, you need a typedef. In C++ you don't need the typedef, that makes live easier. But C++ rules have been complicated by the need to be able to import already existing C headers which "overloaded" the tag name with a function name. The canonical example of that is the Unix stat() function which uses a struct stat* as argument.
Q3: Standard reading is usually quite difficult... you need to already know that there is no place elsewhere modifying what you are reading. It isn't strange that people knowing how to do that are language lawyer...
You are mistaken about the second comment. In S::x, the S is a name in a nested name specifier. What the Standard refers to with "base-specifier" is the following
namespace B { struct X { }; void X() }
struct A : B::X { }; // B::X is a base-specifier
You are also not correct about this:
::S(); // nested name specifier, ignores the struct declaration 'S'.`
That code calls the function not because ::S would be a nested-name-specifier (it isn't a nested-name-specifier!), but because function names hide class or enumeration names if both the function and the class/enumeration are declared in the same scope.
FWIW, the following code would be equally valid for line 2 of your main
p->S::f();
What's important is that S preceedes a ::, which makes lookup ignore the function. That you put :: before S has no effect in your case.
In C++, is there any difference between:
struct Foo { ... };
and:
typedef struct { ... } Foo;
In C++, there is only a subtle difference. It's a holdover from C, in which it makes a difference.
The C language standard (C89 §3.1.2.3, C99 §6.2.3, and C11 §6.2.3) mandates separate namespaces for different categories of identifiers, including tag identifiers (for struct/union/enum) and ordinary identifiers (for typedef and other identifiers).
If you just said:
struct Foo { ... };
Foo x;
you would get a compiler error, because Foo is only defined in the tag namespace.
You'd have to declare it as:
struct Foo x;
Any time you want to refer to a Foo, you'd always have to call it a struct Foo. This gets annoying fast, so you can add a typedef:
struct Foo { ... };
typedef struct Foo Foo;
Now struct Foo (in the tag namespace) and just plain Foo (in the ordinary identifier namespace) both refer to the same thing, and you can freely declare objects of type Foo without the struct keyword.
The construct:
typedef struct Foo { ... } Foo;
is just an abbreviation for the declaration and typedef.
Finally,
typedef struct { ... } Foo;
declares an anonymous structure and creates a typedef for it. Thus, with this construct, it doesn't have a name in the tag namespace, only a name in the typedef namespace. This means it also cannot be forward-declared. If you want to make a forward declaration, you have to give it a name in the tag namespace.
In C++, all struct/union/enum/class declarations act like they are implicitly typedef'ed, as long as the name is not hidden by another declaration with the same name. See Michael Burr's answer for the full details.
In this DDJ article, Dan Saks explains one small area where bugs can creep through if you do not typedef your structs (and classes!):
If you want, you can imagine that C++
generates a typedef for every tag
name, such as
typedef class string string;
Unfortunately, this is not entirely
accurate. I wish it were that simple,
but it's not. C++ can't generate such
typedefs for structs, unions, or enums
without introducing incompatibilities
with C.
For example, suppose a C program
declares both a function and a struct
named status:
int status(); struct status;
Again, this may be bad practice, but
it is C. In this program, status (by
itself) refers to the function; struct
status refers to the type.
If C++ did automatically generate
typedefs for tags, then when you
compiled this program as C++, the
compiler would generate:
typedef struct status status;
Unfortunately, this type name would
conflict with the function name, and
the program would not compile. That's
why C++ can't simply generate a
typedef for each tag.
In C++, tags act just like typedef
names, except that a program can
declare an object, function, or
enumerator with the same name and the
same scope as a tag. In that case, the
object, function, or enumerator name
hides the tag name. The program can
refer to the tag name only by using
the keyword class, struct, union, or
enum (as appropriate) in front of the
tag name. A type name consisting of
one of these keywords followed by a
tag is an elaborated-type-specifier.
For instance, struct status and enum
month are elaborated-type-specifiers.
Thus, a C program that contains both:
int status(); struct status;
behaves the same when compiled as C++.
The name status alone refers to the
function. The program can refer to the
type only by using the
elaborated-type-specifier struct
status.
So how does this allow bugs to creep
into programs? Consider the program in
Listing 1. This program defines a
class foo with a default constructor,
and a conversion operator that
converts a foo object to char const *.
The expression
p = foo();
in main should construct a foo object
and apply the conversion operator. The
subsequent output statement
cout << p << '\n';
should display class foo, but it
doesn't. It displays function foo.
This surprising result occurs because
the program includes header lib.h
shown in Listing 2. This header
defines a function also named foo. The
function name foo hides the class name
foo, so the reference to foo in main
refers to the function, not the class.
main can refer to the class only by
using an elaborated-type-specifier, as
in
p = class foo();
The way to avoid such confusion
throughout the program is to add the
following typedef for the class name
foo:
typedef class foo foo;
immediately before or after the class
definition. This typedef causes a
conflict between the type name foo and
the function name foo (from the
library) that will trigger a
compile-time error.
I know of no one who actually writes
these typedefs as a matter of course.
It requires a lot of discipline. Since
the incidence of errors such as the
one in Listing 1 is probably pretty
small, you many never run afoul of
this problem. But if an error in your
software might cause bodily injury,
then you should write the typedefs no
matter how unlikely the error.
I can't imagine why anyone would ever
want to hide a class name with a
function or object name in the same
scope as the class. The hiding rules
in C were a mistake, and they should
not have been extended to classes in
C++. Indeed, you can correct the
mistake, but it requires extra
programming discipline and effort that
should not be necessary.
One more important difference: typedefs cannot be forward declared. So for the typedef option you must #include the file containing the typedef, meaning everything that #includes your .h also includes that file whether it directly needs it or not, and so on. It can definitely impact your build times on larger projects.
Without the typedef, in some cases you can just add a forward declaration of struct Foo; at the top of your .h file, and only #include the struct definition in your .cpp file.
There is a difference, but subtle. Look at it this way: struct Foo introduces a new type. The second one creates an alias called Foo (and not a new type) for an unnamed struct type.
7.1.3 The typedef specifier
1 [...]
A name declared with the typedef specifier becomes a typedef-name. Within the scope of its declaration, a
typedef-name is syntactically equivalent to a keyword and names the type associated with the identifier in
the way described in Clause 8. A typedef-name is thus a synonym for another type. A typedef-name does not introduce a new type the way a class declaration (9.1) or enum declaration does.
8 If the typedef declaration defines an unnamed class (or enum), the first typedef-name declared by the declaration
to be that class type (or enum type) is used to denote the class type (or enum type) for linkage
purposes only (3.5). [ Example:
typedef struct { } *ps, S; // S is the class name for linkage purposes
So, a typedef always is used as an placeholder/synonym for another type.
You can't use forward declaration with the typedef struct.
The struct itself is an anonymous type, so you don't have an actual name to forward declare.
typedef struct{
int one;
int two;
}myStruct;
A forward declaration like this wont work:
struct myStruct; //forward declaration fails
void blah(myStruct* pStruct);
//error C2371: 'myStruct' : redefinition; different basic types
An important difference between a 'typedef struct' and a 'struct' in C++ is that inline member initialisation in 'typedef structs' will not work.
// the 'x' in this struct will NOT be initialised to zero
typedef struct { int x = 0; } Foo;
// the 'x' in this struct WILL be initialised to zero
struct Foo { int x = 0; };
There is no difference in C++, but I believe in C it would allow you to declare instances of the struct Foo without explicitly doing:
struct Foo bar;
Struct is to create a data type.
The typedef is to set a nickname for a data type.