C++ namespace collision in copy constructor - c++

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;
};

Related

Specifying namespaces explicitly inside method definitions

Let's suppose I have a namespace Foo and I have declared a class Bar inside of it with a constructor inheriting a class Base with its constructor along with some other class Baz with a publicly accessible method boo():
namespace Foo {
class Baz {
public:
void boo();
};
class Base {
public:
Base();
};
class Bar: public Base {
public:
Bar();
};
}
Now I want to define the Bar constructor in my implementation as follows:
Foo::Bar::Bar(): Foo::Base::Base() {
Foo::Baz::boo();
}
It appears as though it's OK to write it down like this:
Foo::Bar::Bar(): Base() {
Baz::boo();
}
Meaning that once I specify the namespace in Foo::Bar::Bar() explicitly, there is no need to specify it later in the definition of this method.
Does it work like that everywhere from the explicit mentioning of the namespace up to the end of the definition?
If we look at your Bar constructor definition:
Foo::Bar::Bar(): Base() {
Baz::boo();
}
Once the declaration-part of the constructor (Foo:::Bar::Bar) have been read by the compiler, it knows the scope and it's no longer needed.
A more interesting example would be e.g.
namespace Foo
{
struct Baz {};
struct Bar
{
Baz fun(Baz);
};
}
Foo::Baz Foo::Bar::fun(Baz)
{
// Irrelevant...
}
Now, for the definition of the structure itself, Baz doesn't need any namespace-qualifier since it's defined in the namespace and all the symbols of the namespace is available directly.
The definition of the function fun is a different. Because it's not defined inside the namespace, we need to fully qualify the Baz structure for the return type. And the same for the actual function-name. But then like before once that part is read and parsed by the compiler, it knows the scope and knows that the argument Baz is really Foo::Baz.
You can read more about name lookup in this reference.

Calling a static method by repeating the object name?

I have a singleton:
struct foo {
static foo& instance() {
static foo f;
return f;
}
};
When re-arranging some code I ended up with this statement "by error":
foo::foo::instance()
But this is deemed correct by my compiler (gcc 4.7). In fact, even foo::foo::foo::instance() compiles. Why?
It is due to "injected-name" — which means if foo is a class-name, and the same name "foo" is also injected into the class-scope which is why your code works. It is 100% Standard-conformant.
Here is one interesting example which shows the benefits of this feature:
namespace N
{
//define a class here
struct A
{
void f() { std::cout << "N::A" << std::endl; }
};
}
namespace M
{
//define another class with same name!
struct A
{
void f() { std::cout << "M::A" << std::endl; }
};
struct B : N::A //NOTE : deriving from N::A
{
B()
{
A a;
a.f(); //what should it print?
}
};
}
What should a.f() call? What is the type of a? Is it M::A or N::A? The answer is, N::A, not M::A.
Online Demo
It is because of name-injection, N::A is available inside the constructor of B without qualification. It also hides M::A, which remains outside the scope of B. If you want to use M::A, then you've to write M::A (or better ::M::A).
Because of [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.
So foo::foo is an injected class name, denoting foo itself.
Actually it's a bit more complicated: according to [class.qual]/2, foo::foo alone denotes a constructor of foo. In order to denote a class, it should either be preceded by struct (making it elaborated-type-specifier), or followed by :: (making it a nested-name-specifier - this is your case), or be a base-specifier (for example struct bar : foo::foo {};).
As stated in the other answers, the reason is name injection. To me, the main use case would be the following
struct B1 { void f(){} };
struct B2 { void f(){} };
struct D : B1, B2 { }
int main() {
D obj;
obj.f();
}
In main the call to f is ambiguous and won't compile. The way to be specific is a qualified call, ie
obj.B1::f();

why can't I access this method via inheritance? [duplicate]

This question already has answers here:
C++ method only visible when object cast to base class?
(7 answers)
Closed 8 years ago.
I have two simple classes, and wish to access the public method stuff by passing an int value. why can't I do that with an instance of Bar? Shouldn't it inherit the public method stuff. The type hinting gives the int a parameter, but it doesn't compile.
class Foo
{
public:
int a;
void stuff(int a){ std::cout << a << std::endl; }
};
class Bar : public Foo
{
protected:
void stuff() { std::cout << "hello world"; }
};
void main()
{
Bar b
b.stuff(3);
}
Because Bar::stuff hides Foo::stuff (only the name matters when overload resolution is performed, parameters are ignored).
You can :
Bring it into sope with a using declaration
Or alternatively, explicitly qualify the call e.g. b.Foo::stuff(3);.
Note :
main() must return an int.
#include <iostream>
class Foo
{
public:
int a;
void stuff(int a){ std::cout << a << std::endl; }
};
class Bar : public Foo
{
public:
using Foo::stuff;
protected:
void stuff() { std::cout << "hello world"; }
};
int main()
{
Bar b;
b.stuff(3);
}
Or :
int main()
{
Bar b;
b.Foo::stuff(3);
}
When looking up the name stuff, the one in Bar found first. Once that is found, the access privileges are checked. Since Bar::stuff is protected, you are not able to use it from main.
From the draft standard:
10.2 Member name lookup [class.member.lookup]
1 Member name lookup determines the meaning of a name (id-expression) in a class scope (3.3.7). Name lookup can result in an ambiguity, in which case the program is ill-formed. For an id-expression, name lookup begins in the class scope of this; for a qualified-id, name lookup begins in the scope of the nestedname-specifier. Name lookup takes place before access control (3.4, Clause 11).
In C++, name hiding can take place when one function in base class has the same name as one function in derived class.
Phases of the function call process
Name lookup
Overload resolution
Access control
Name lookup stops looking for other names as soon as it finds a name in derived class Bar. Therefore, Bar::stuff() hides any function with name stuff in Foo.
After the name lookup process,
overload resolution fails since there is no stuff(int) in Bar.
even though stuff() without int parameter is called, access control fails since stuff() is protected.
b.Foo::stuff(3);
Or, you can do a trick to access any protected:)
void main()
{
Bar b;
class BarAccess : public Bar { friend void main(); }
BarAccess * ba = reinterpret_cast<BarAccess *>(&b);
ba->stuff(3);
ba->stuff();
}

Function and struct having the same name in c++

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 .

delegating into private parts

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.