The following code compiles in C++
struct foo
{
int a, b;
};
struct foo foo()
{
struct foo a;
return a;
}
int main(void) {
foo();
return 0;
}
Is it supposed to be allowed to have a struct and a function with the same name ?
Since it compiles I then go on and try to declare an object of type foo. Is there a way? It seems impossible to do :
foo a; // error: expected ‘;’ before ‘a’
foo a{}; // error: expected ‘;’ before ‘a’
foo a(); // most vexing parse would kick in any way
Yes, this is allowed we can see this by going to draft C++ standard section 3.3.10 Name hiding paragraph 2 and it says (emphasis mine):
A class name (9.1) or enumeration name (7.2) can be hidden by the name of a variable, data member, function, or enumerator declared in the same scope. If a class or enumeration name and a variable, data member, function, or enumerator are declared in the same scope (in any order) with the same name, the class or enumeration name is hidden wherever the variable, data member, function, or enumerator name is visible.
In this case using struct in the declaration would fix your issue:
struct foo a;
Usually a bad habbit to do something like that. I would name it foo_s or whatever to distinguish it from the function. Other than that, there isn't really a way of doing it.
In C this is possible, since it requires
struct foo
instead of just
foo
as the type name (unless it is typedef'd)
Yes, you can, but it's a really bad pattern to get into.
struct foo
{
};
foo foo(foo& f)
{
return f;
}
int main()
{
struct foo f;
foo(f);
return 0;
}
See livedemo: http://ideone.com/kRK19f
The trick was to specify struct foo when we wanted to get at the type. Note that, until you create this ambiguity, it's actually not necessary to keep saying struct, this isn't C (as in the line foo foo(foo& f)).
Most developers choose a camel casing pattern, e.g they use an upper case letter to distinguish type names and a lowercase letter for a function name:
struct Foo
{
};
Foo foo(); // no ambiguity.
Back in Microsoft's prime, many Windows developers acquired the habit of prefixing struct/class definitions, the definition of a class of thing if you will, with a capital C
struct CFoo
{
};
Now, even if you want to use upper-case first letters for your function names, there is no ambiguity.
Just do it like you would in C, using:
struct foo a;
You might even initialise it like this:
struct foo a{};
struct foo a = {0};
A workaround would be using a typedef, thus avoiding any ambiguity and other difficulties:
typedef struct foo s_foo;
From The.C++.Programming.Language.Special.Edition $A.8:
To preserve C compatibility, a class and a non-class of the same name can be declared in the same
scope ($5.7). For example:
struct stat { /* ... */ };
int stat(char * name, struct stat * buf);
In this case, the plain name (stat) is the name of the non-class. The class must be referred to using
a class-key prefix .
Related
I am a bit confused when using struct in c/c++. Traditionally, when I use struct, I usually use it as:
typedef struct Name{
int a;
};
Name var;
Although it is considered a bad practice from Linus, it's somehow common.
Yet, I wonder
struct Name{
int a;
};
Name var;
Seems to serve the same purpose, is typedef really necessary?
In fact, shouldn't it be
struct Name{
int a;
};
struct Name var;
Why is the struct from "Name" omitted? If it can always be omitted, does that mean typedef struct is totally useless?
For:
typedef struct Name{
int a;
};
Name var;
The definition should be:
typedef struct Name{
int a;
} Name;
Name var;
Otherwise you are not aliasing the type.
In C++ this doesn't make sense, when you declare struct Name you can already instantiate Name omitting the struct keyword, as you do in the second code snippet, which would not work for C. It behaves similarly to class, in this regard, you don't declare class Name var;, just Name var;.
In C I don't agree it's a bad practice, it's a user defined type, why would you always use struct if you can omit it, any programmer worthy of that name should be able to identify a user defined type, it's not rocket science. This though is opinion based. If it's bad practice we will need to revise the whole notion, not only in C++ but also C#, where class and struct keywords are always omitted when instantiating objects.
As for aliasing pointers, I completely agree, I do not like it one bit, though this can also be seen as opinion based.
So to answer your direct questions:
Seems to serve the same purpose, is typedef really necessary?
For the purpose you describe in C yes, in C++ no.
Why is the struct from "Name" omitted?
In C it cannot be ommited, unless you typedefine it, in C++ not only it can, but it should, it's not needed at all.
If it can always be omitted, does that mean typedef struct is totally useless?
As you can see, it's not useless.
Always using struct keyword while initializing a variable could be lengthy (or whatever you think). That's why there's a typedef keyword (although it have many other uses too).
You can declare a struct with typedef like this:
typedef struct{
int a;
}var;
or
struct Name{
int a;
};
typedef struct Name var;
Then use it like:
var my_age;
However, the above explanation covers only C, whereas in C++ structs are similar to classes but their members are public by default.
So, in C++ you can directly use the struct's name without typing struct keyword again n again
struct Name {
int a;
};
Name my_age;
In C and C++, rules are different. The code you show is clearly C++, it wouldn’t compile in C.
With the following definitions:
struct Foo {
/*fields*/
};
typedef struct Bar {
/*fields*/
} Baz;
in C, variable declarations struct Foo var, struct Bar var, Baz var are valid, but plain Foo var or Bar var are not. In C++ all such variable declarations are valid. Thus, C code would typically look like:
struct Foo {
/*fields*/
};
typedef struct {
/*fields*/
} Baz;
struct Foo var1;
Baz var2;
while in C++, the typical form is:
struct Foo {
/*fields*/
};
Foo var;
UPD: technically, that’s because in struct Foo {..., in C type name is struct Foo; while in C++ the name is simply Foo, and struct is only needed to declare the type, not to use it.
I have the following code:
namespace A {
struct Foo {
int a;
};
}
struct Foo {
int b;
};
struct Bar : public A::Foo {
Bar(Foo foo) {
c = foo.b;
}
int c;
};
C++ compilers complains at "c = foo.b" because A::Foo does not have a member named b.
If I change the type of Bar parameter with ::Foo it works.
My question is what is the rational behind this behaviour (I suppose it has to do with the fact that the inheritance makes Bar enter the A namespace but I cannot find any documentation to support this theory.
Every class has its name injected into it as a member. So you can name A::Foo::Foo. This is called the injected class name.
[class]
2 A class-name is inserted into the scope in which it is declared
immediately after the class-name is seen. The class-name is also
inserted into the scope of the class itself; this is known as the
injected-class-name. For purposes of access checking, the
injected-class-name is treated as if it were a public member name.
[basic.lookup]
3 The injected-class-name of a class is also considered to be a
member of that class for the purposes of name hiding and lookup.
Because unqualified name lookup of the argument type begins in the scope of the class Bar, it will continue into the scope of its base class to account for any member there. And it will find A::Foo::Foo as a type name.
If you want to use the global type name, simply qualify it by its surrounding (global) namespace.
Bar(::Foo foo) {
c = foo.b;
}
Which is doing fully qualified lookup in a scope where the injected class name doesn't appear.
For a followup "why" question see
Why is there an injected class name?
Not a complete answer, only code that shows (since it compiles) that Bar does not enter the namespace A. You can see that when inheriting from A::Foo1 there is no problem with ambiguity of Foo which would be different if this inheritance lets Bar enter A.
namespace A {
struct Foo {
int a;
};
struct Foo1 {
int a;
};
}
struct Foo {
int b;
};
struct Bar : public A::Foo1 {
Bar(Foo foo) {
c = foo.b;
}
int c;
};
In C++ consider the grammar rule:
member-access-expression: LHS member-access-operator RHS
(op is .)
and
LHS=unqualified id-expression e.g. that references an instance variable.
RHS=qualified id-expression (with at least one nested identifier)
example: a.b::c
If that can ever pass the semantic check, what situation would it be ?
The following experiment:
struct B{};
struct A
{
B b;
};
int main()
{
A a;
a.b::c;
}
returns
'b' is not a class, namespace, or enumeration
a.b::c;
^
(demo)
This tends to hint to me that there can't be any legal case of a qualified-id on the right of a member access.
A very simple example is if you want to call a member function of a parent class:
struct A {
void f();
};
struct B: A {
void f();
};
B b;
b.A::f();
One use case is accessing members of an enum within some struct A by using an instance of A (rather than using the enum directly via A::b::c):
struct A {
enum class b { c }; // can be unscoped as well
};
A a;
a.b::c; // Access to enum value c - similarly, A::b::c would work
Here's a trivial example:
struct A {
void f() {}
};
int main()
{
A a;
a.A::f();
}
A::f() is a qualified version of the name for the function f that's a member of A. You can use it in member access just like the "short" (or unqualified) name.
In fact, one might argue that every time you write a.f(), that's a shortcut for a.A::f() (with the A:: part being taken automatically from decltype(a)).
There's nothing magic about this, though it's unusual to see the construct outside of the sort of scenarios the other answerers demonstrated, because in this example it's redundant.
While reading about the visitor pattern I ran into this snippet of code:
virtual void visit(class Composite *, Component*) = 0;
This is a member function, and it seems to be forward declaring the class Composite inside its parameters. I tried this with just a normal function, like so:
void accept(class A a);
for some class A that I haven't declared or defined yet and the code worked fine. Why is this allowed? How, if at all, is it different from forward declaring before the line? Has anything changed recently in the standard in regards to this?
Many people are claiming this is a leftover of C, but then why does this code compile fine in C++, but not C?
#include <stdio.h>
int process(struct A a);
struct A{
int x;
};
int process(struct A a){
return a.x;
}
int main(void)
{
struct A a = {2};
printf("%d", process(a));
return 0;
}
This is called an incomplete type, and is a concept C++ inherited from C.
Incomplete types work this way: before you've defined a class B in your code, you can use class B varname as, say, an argument in function prototypes, or use pointers to this type as class B* ptr - anywhere where no details about a type besides its name are really needed.
Actually, you can write it differently - just put a class B; (which should work as a class declaration) before you use it as an incomplete type, and then you can write B varname instead of class B varname.
Pointers to incomplete types are often used with opaque pointers, which are probably the most common use of incomplete types in C++. Opaque pointers are described well enough in the linked Wikipedia article. Put short, it is a technique that allows your API to hide an entire class implementation.
Using the incomplete type syntaxis you describe in your question, the example code from Wikipedia:
//header file:
class Handle {
public:
/* ... */
private:
struct CheshireCat; // Not defined here
CheshireCat* smile; // Handle
};
//CPP file:
struct Handle::CheshireCat {
int a;
int b;
};
can be rewritten as:
//header file:
class Handle {
public:
/* ... */
private:
struct CheshireCat* smile; // Handle
};
//CPP file:
struct CheshireCat {
int a;
int b;
};
Note this: these code snippets are not equivalent, as the former defines a type Handle::CheshireCat, while the latter has it simply as CheshireCat.
On the code you gave as an example:
In C, the reason it doesn't compile is quite simple: the struct A in the function prototype is a declaration scoped to the function prototype, and thus it is different from the struct A which is declared latter. C and C++ have slightly different rules for this specific case. If you forward-declare the struct like this: struct A; before the function prototype, it will compile in both languages!
Other notable uses of this syntaxis:
This syntaxis has an important place as part of C++'s backward compatibility with C. You see, in C, after defining or forward-declaring a struct like this: struct A {}; or struct A;, the type's actual name would be struct A. To use the name as A, you needed to use a typedef. C++ does the latter automatically, but allows you to use A both as struct A and A. Same goes for class-es union-s, and enum-s.
Actually, some argue this has a semantical importance. Consider a function with the following signature: int asdf(A *paramname). Do you know what A is just by looking at the declaration? Is it a class, struct, enum or a union? People say that a signature like that can be made clearer in such a way: int asdf(enum A *paramname). This is a nice way of writing self-documenting code.
In C, structure names were not accessible without the struct keyword:
struct Foo {};
void bar(struct Foo foo) {...}
You could get around this by using a typedef as well:
typedef struct Foo {} Foo;
void bar(Foo foo) {...}
In C++, this remains for backward compatibility. It's been logically extended, including support for the class keyword instead of struct. class Composite * is almost equivalent to just saying Composite * in this regard. It is not necessarily used as a forward declaration, just accessing the type name.
Note that it can still be used to disambiguate if necessary:
struct Foo {};
void Foo();
int main() {
Foo foo; //error: Foo refers to the function
struct Foo foo; //okay: struct Foo refers to the class
}
Now the same declaration can introduce a type name, like it does in your accept example and possibly does in the visit example. For a function at namespace scope, if the class being declared is not found, it will be declared in the namespace containing the function (see N4140 [basic.scope.pdecl]/7).
This means that the following will not compile due to the struct/union mismatch:
void foo(struct Bar bar);
union Bar;
The above code is roughly equivalent to:
struct Bar;
void foo(Bar bar);
union Bar;
Sometimes, C++'s notion of privacy just baffles me :-)
class Foo
{
struct Bar;
Bar* p;
public:
Bar* operator->() const
{
return p;
}
};
struct Foo::Bar
{
void baz()
{
std::cout << "inside baz\n";
}
};
int main()
{
Foo::Bar b; // error: 'struct Foo::Bar' is private within this context
Foo f;
f->baz(); // fine
}
Since Foo::Bar is private, I cannot declare b in main. Yet I can call methods from Foo::Bar just fine. Why the hell is this allowed? Was that an accident or by design?
Oh wait, it gets better:
Foo f;
auto x = f.operator->(); // :-)
x->baz();
Even though I am not allowed to name the type Foo::Bar, it works just fine with auto...
Noah wrote:
type names defined within a class definition cannot be used outside their class without qualification.
Just for fun, here is how you can get at the type from outside:
#include <type_traits>
const Foo some_foo();
typedef typename std::remove_pointer<decltype( some_foo().operator->() )>::type Foo_Bar;
Trying to find anything in the standard that would spell it out in detail but I can't. The only thing I can find is 9.9:
Type names obey exactly the same scope rules as other names. In particular, type names defined within a class definition cannot be used outside their class without qualification.
Essentially, the name of Foo::Bar is private to Foo, not the definition. Thus you can use Bars outside of Foo, you just can't refer to them by type since that name is private.
The name lookup rules for members would also seem to have some effect on this. I don't see anything that specifically references "nested class" and thus they wouldn't be allowed to (if my lack of finding anything in fact is because it's not there).
I can't provide a full answer, but maybe a starting point. The C++ 1998 specification includes the following code example under paragraph 11.3 [class.access] (p. 175):
class A
{
class B { };
public:
typedef B BB;
};
void f()
{
A::BB x; // OK, typedef name A::BB is public
A::B y; // access error, A::B is private
}
In this example, a private type is "published" through a public typedef. Although it's not the same thing as publishing a type through a member function signature, it's similar.
I think this is by design. You cannot explicitly create instance of Foo::Bar but it could be returned from member functions and then you could pass it to other member functions. This lets you to hide implementation details of your class.