Calling a static method by repeating the object name? - c++

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();

Related

Why are methods and attributes of base template classes not immediately available? [duplicate]

Why is it that the C++ standard specify that unqualified names in a template are non-dependent?
e.g.
template<typename T>
class Base
{
public:
T x;
};
template<typename T>
class C : public Base<T>
{
public:
bool m() { return x == 0; } // Error: undeclared identifier 'x'
};
Quoting from the accepted answer to an SO question about how to overcome the restriction:
The standard specifies that unqualified names in a template are
non-dependent and must be looked up when the template is defined. The
definition of a dependent base class is unknown at that time
(specializations of the base class template may exist) so unqualified
names are unable to be resolved.
However, the quoted and other answers do not specify why this is what the standard specifies. What is the rationale for this restriction?
This isn't quite what the standard actually says. What it actually says is that dependent base classes are not examined during unqualified name lookup. An unqualified name can of course be dependent given the correct context - that's how ADL in templates works: given a template type parameter T, the foo in foo(T()) is a dependent name.
In any event, the reason it can't do this kind of lookup is straightforward: at template definition time, you have no idea what the dependent base class is going to look like, thanks to specializations that may come in later, so you can't do any meaningful lookup. Every misspelled identifier in a template with a dependent base class can't be diagnosed until when it is instantiated, if ever. And since every unqualified identifier might have been from a dependent base class, you'll need some way to answer "is this a type?" and "is this a template?", since the answers to those questions affect parsing. That means something like the dreaded typename and template keywords, but in far more places.
I think it is a matter of consistency. Consider this, a bit modified example:
header file:
template<typename T>
class Base
{
public:
T x;
};
extern int x;
template<typename T>
class C : public Base<T>
{
public:
bool m() { return x == 0; }
};
and source file:
template<>
class Base<int> // but could be anything
{
public:
// no x here
};
int main()
{
C<char> c1;
c1.m(); // may select ::x or Base<char>::x
C<int> c2;
c2.m(); // has only one choice: ::x
return(0);
}
Wording in the standard guarantees that compiler will either error out or select whatever symbol it sees at the point of template definition. If the compiler was to defer name resolution to template instantiation it may then select different objects visible at this point and which may surprise the developer.
If the developer WANTS to access dependent name he is required to state this explicitly and he shouldn't be then taken off guard.
Please also note that if the x wasn't available at the point of template definition the following code would break (unexpectedly) One Definition Rule:
one.cpp
#include <template_header>
namespace {
int x;
}
void f1()
{
C<int> c1;
}
two.cpp
#include <template_header>
namespace {
char x;
}
void f2()
{
C<int> c2;
}
One would expect that c1 and c2 variables are of the same type and can for example be safely passed to a function taking C<int> const & parameter, but basically the two variables have the same type name but the implementations differ.
Whether compliant with the standard or not, in Visual Studio 2015 - this isn't an issue at all. Moreover, despite the comment from Tomek, the compiler takes the correct x
static int x = 42;
template<typename T>
class Base {
public:
T x;
Base() { x = 43; }
};
template<>
class Base<int> { };
template<typename T>
class C :public Base<T>
{
public:
int m() { return x; }
};
void main() {
C<int> cint;
C<char> cchar;
std::cout << "cint: " << cint.m() << std::endl;
std::cout << "cchar: " << cchar.m() << std::endl;
}
// Output is:
// cint: 42
// cchar: 43

C++ namespace collision in copy constructor

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

Is there a context where the expression `a.b::c` makes sense?

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.

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

c++ and injected base name

The following code does not compile in gcc:
namespace One{
class A{
};
};
namespace Two{
class A{
public:
void what(){
cout << "Two::A says what!" << endl;
}
};
class B : public One::A{
public:
B(){
A xx;
xx.what();
}
};
};
And it gives:
gccbug.cpp: In constructor ‘Two::B::B()’:
gccbug.cpp:23: error: ‘class One::A’ has no member named ‘what’
Now, I was told that this is correct behavior (due to injected base name of One::A making A refer to One::A). However, this code compiles in C# (well, after changing a few things), so this seems to be c++ specific.
What I'm wondering is.. why? Is there a specific purpose for injecting the base name "One::A" as "A"?
The only reason I can think of is that in C++ you are likely to refer to the base class name in the initializer list of the constructor, like this:
namespace Two {
/*...*/
class B : public One::A {
public:
B():A()
{
/*...*/
}
};
}
Of course the purpose then is different from the one in your example, because you actually declare a local variable inside the constructor, whereas in my example, the A() refers to the object of type A that is implicit in the definition of class B due to inheritance.
However, the situation of my example is more likely to occur, so I guess they thought let's not require the namespace to be made explicit in this case. As a consequence, any reference to A without a namespace is interpreted as referring to the base class, rather than any other class named A, even if it is in the same namespace as the declaration of B.
Is there a specific purpose for injecting the base name "One::A" as "A"?
Yes. It is so that you could write this:
namespace N
{
class A
{
A *a;
};
}
In the absence of injected-name, you've to write N::A *a which is not nice.
Note that it is because of injected-name, the following lines are allowed:
A::A *a1; //ok
A::A::A *a2; //ok
A::A::A::A *a3; //ok
A::A::A::A::A *a4; //ok
//and so on
Online demo
By qualifying A with One:: you added the A from namespace one in scope, so the compiler will look there for it's name resolution.