In C++, what is the purpose of the scope resolution operator when used without a scope? For instance:
::foo();
It means global scope. You might need to use this operator when you have conflicting functions or variables in the same scope and you need to use a global one. You might have something like:
void bar(); // this is a global function
class foo {
void some_func() { ::bar(); } // this function is calling the global bar() and not the class version
void bar(); // this is a class member
};
If you need to call the global bar() function from within a class member function, you should use ::bar() to get to the global version of the function.
A name that begins with the scope resolution operator (::) is looked up in the global namespace. We can see this by looking at the draft C++ standard section 3.4.3 Qualified name lookup paragraph 4 which says (emphasis mine):
A name prefixed by the unary scope operator :: (5.1) is looked up in global scope, in the translation unit where it is used. The name shall be declared in global namespace scope or shall be a name whose declaration is visible in global scope because of a using-directive (3.4.3.2). The use of :: allows a global name to be referred to even if its identifier has been hidden (3.3.10).
As the standard states this allows us to use names from the global namespace that would otherwise be hidden, the example from the linked document is as follows:
int count = 0;
int main(void) {
int count = 0;
::count = 1; // set global count to 1
count = 2; // set local count to 2
return 0;
}
The wording is very similar going back to N1804 which is the earliest draft standard available.
Also you should note, that name resolution happens before overload resolution. So if there is something with the same name in your current scope then it will stop looking for other names and try to use them.
void bar() {};
class foo {
void bar(int) {};
void foobar() { bar(); } // won't compile needs ::bar()
void foobar(int i) { bar(i); } // ok
}
When you already have a function named foo() in your local scope but you need to access the one in the global scope.
My c++ is rusty but I believe if you have a function declared in the local scope, such as foo() and one at global scope, foo() refers to the local one. ::foo() will refer to the global one.
referring to the global scope
Related
Consider following code snippet:
enum class Bar {
A
};
void foo(Bar) {}
struct Baz {
void foo() {
foo(Bar::A);
}
};
It fails to compile, the message from gcc 9.2 is:
:12:19: error: no matching function for call to 'Baz::foo(Bar)'
12 | foo(Bar::A);
|
I don't suspect it is a bug since clang 10 also fails. I have two questions regarding this situation:
Where does standard define bahaviour for such overloads?
What are the possible reasons that compiler behaviour is specified that way?
live example
The call to foo inside Baz::foo() will only look up names inside the class. If you mean to use the foo declared outside the class Baz, you need to use the scope-resolution operator, like this:
enum class Bar {
A
};
void foo(Bar) {}
struct Baz {
void foo() {
::foo(Bar::A); // looks up global 'foo'
}
};
Note that the unscoped call to foo fails because there is a Bar::foo that is found in the closest scope. If you name the function differently, then no function is found in Bar, and the compiler will look in the outer scope for the function.
enum class Bar {
A
};
void foo(Bar) {}
struct Baz {
void goo() { // not 'foo'
foo(Bar::A); // this is fine, since there is no 'Bar::foo' to find
}
};
Here's the quote from cppreference for a class definition.
e) if this class is a member of a namespace, or is nested in a class that is a member of a namespace, or is a local class in a function that is a member of a namespace, the scope of the namespace is searched until the definition of the class, enclosing class, or function. if the lookup of for a name introduced by a friend declaration: in this case only the innermost enclosing namespace is considered, otherwise lookup continues to enclosing namespaces until the global scope as usual.
Of course, this only applies to class definitions, but for member functions (which is your example), it says
For a name used inside a member function body, a default argument of a member function, exception specification of a member function, or a default member initializer, the scopes searched are the same as in [class definition], ...
So the same logic applies.
According to the rule of unqualified name lookup, from the standard, [basic.lookup.unqual]/1,
(emphasis mine)
In all the cases listed in [basic.lookup.unqual], the scopes are searched for a declaration in the order listed in each of the respective categories; name lookup ends as soon as a declaration is found for the name.
That means the name foo is found at the class scope (i.e. the Baz::foo itself), then name lookup stops; the global one won't be found and considered for the overload resolution which happens later.
About your 2nd question, functions can't be overloaded through different scopes; which might cause unnecessary confusion and complexity. Consider the following code:
struct Baz {
void foo(int i) { }
void foo() {
foo('A');
}
};
You know 'A' would be converted to int then passed to foo(int), that's fine. If functions are allowed to be overloaded through scopes, if someday a foo(char) is added in global scope by someone or library, behavior of the code would change, that's quite confusing especially when you don't know about the adding of the global one.
This question already has answers here:
redefinition of variable inside scope
(4 answers)
Closed 3 years ago.
In this following code foo() is parsed in two different places and calls two different functions (marked by the ********).
#include <cstdio>
typedef int (*func)(void);
int bar()
{
printf("bar\n");
return 4; // guaranteed to be random
}
int foo()
{
printf("foo\n");
static int i = 0;
if(i)
return i;
++i;
i = foo(); // recursive call ********
printf("%d\n", i);
func foo = bar;
i = foo(); // calls bar. Why? ********
printf("%d\n", i);
return i;
}
int main()
{
return foo();
}
In all the compilers I was able to try (gcc, clang, MSVC, and a couple others), the output is:
foo
foo
1
bar
4
Why does the compiler choose to call bar via the function pointer and mask a recursive call? Is this behavior defined? If so, can I please have a reference?
Yes, this behavior is defined and is called name hiding, scope hiding, or shadowing. See this answer by Victor Polevoy, relevant section quoted below.
From N4296:
3.3.10 Name hiding [basic.scope.hiding]
A name can be hidden by an explicit declaration of that same name in a nested declarative region or derived class.
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 a member function definition, the declaration of a name at block scope hides the declaration of a member of the class with the same
name; see 3.3.7. The declaration of a member in a derived class
(Clause 10) hides the declaration of a member of a base class of the
same name; see 10.2.
During the lookup of a name qualified by a namespace name, declarations that would otherwise be made visible by a using-directive
can be hidden by declarations with the same name in the namespace
containing the using-directive; see (3.4.3.2).
If a name is in scope and is not hidden it is said to be visible
In this case it is also point 1: the declaration of the name foo in the function is hiding the declaration of the function name foo in the outer scope.
I have a following snippet code of c++. Declared a class inside main() function.
What is the reason to we can not define friend function in local class?
#include<iostream>
int main()
{
class Foo
{
void foo() {} // Ok
friend void Bar(){}; // Error
};
}
There's a practical reason. First and foremost, an inline friend definition cannot be found by either qualified or unqualified lookup. It can only by found by ADL. So if we take the class from your example, put it in global scope and try to call Bar:
class Foo
{
friend void Bar(){};
void foo() {
Bar();
}
};
We'll be notified that Bar was not declared in that scope. So if it was in a local class. You can't call it from the members. You can't call it inside the function. The only way you may call it involves either some hoops or ADL. So the language just doesn't allow for it. It's not deemed a useful feature.
There is no convincing technical reason for this. ADL can't find it, you say? Well, that's basically part of the question: why can't ADL find it? Just extend ADL to make it find it.
One design-level reason for this limitation is probably rooted in the language treatment of unqualified names in friend declarations.
Unqualified names used in friend declarations in local classes refer to names from nearest enclosing non-class scope. This treatment of unqualified names is critically important, since this is the only way local classes can refer to each other (since for obvious reasons, local classes do not have qualified names)
int main()
{
class B;
class A {
int x;
friend B; // refers to local `B`
};
class B {
void foo(A &a) { a.x = 42; }
};
}
This rule is also applied to friend function declarations with unqualified names. C++ does not have local functions, but such friend declarations can still refer to a local non-defining declaration of a function (which is perfectly legal)
void foo() {}
int main()
{
void foo(); // refers to `::foo`
class A {
friend void foo(); // refers to local `foo`, which is `::foo`
};
}
Now, what would you propose should happen when one defines a friend function in a local class (using an unqualified name, of course)? What function is introduced by such a declaration? Into what scope, specifically? By definition, it is not a member of the class, since friend declarations do not introduce class members. It cannot be a member of the nearest enclosing local scope, since that would make it a local function and C++ does not support local functions.
We cannot just uniformly change the behavior of all unqualified names in friend declarations and say that they should now refer to names in the nearest enclosing namespace scope, since that would leave as with no way to refer to local classes (as shown above).
The only way out of this situation is to make only in-class friend function definitions refer to (and define) functions in the nearest enclosing namespace scope. Such functions would only be callable through [modified] ADL (and let's say we are OK with that). But that would mean that we'd have to give different treatment to unqualified names in friend function definitions (as opposed to non-defining friend declarations). This would be rather inelegant and confusing. So, the language authors decided against it.
Note that importance of this might have increased notably after C++14, which gave us deduced auto return types in functions. After that local classes became not even nearly as "local" as they used to be
auto foo()
{
struct S // Local class
{
void bar() {}
};
return S();
}
int main()
{
auto a = foo();
a.bar(); // An object of local class used outside of its original scope
typedef decltype(a) S; // Local type is "stolen" from its original scope
S b; // and used to freely declare objects in a completely
b.bar(); // different scope
}
Because member functions of a local class have to be defined entirely inside the class body and friend function not a member function. We declared friend functions inside class and defined outside of class.
According to cppreference:
Local classes
A local class cannot have static members
Member functions of a local class have no linkage
Member functions of a local class have to be defined entirely inside the class body
Local classes other than closure types (since C++14) cannot have member templates
Local classes cannot have friend templates
Local classes cannot define friend functions inside the class definition
A local class inside a function (including member function) can access the same names that the enclosing function can access.
void Foo(int i)
{
}
struct Bar
{
static void Foo() { Foo(1); }
};
The above code does not compile. It cannot find Foo(int). Why? I know it has to do with having the same function name, but did not get further understanding the problem.
Why do I need a qualified lookup?
From 3.4.1 (emphasis mine)
In all the cases listed in 3.4.1, the scopes are searched for a declaration in the order listed in each of the
respective categories; name lookup ends as soon as a declaration is found for the name. If no declaration is
found, the program is ill-formed.
In this particular case the first scope to be searched is the function local scope. Foo is not found there. Then comes the class scope. Since the name Foo is found in it, the name lookup stops there and the other Foo does not participate in overload resolution at all.
If a function in a particular namespace shares the same name as one in a global namespace, then the one in the global namespace is not found.
Unfortunately the C++ standard does not allow you to bring in the global namespace into the current one with an appropriate using statement, although you can use using ::Foo; to pull in that particular function:
void Foo(char)
{
}
struct Bar
{
static void Foo(double) { }
static void Foo() {
using ::Foo;
Foo('c'); // correct overload is found since ::Foo is pulled into scope
Foo(3.0);
}
};
Otherwise you need to use the scope resolution operator to find the global function:
struct Bar
{
static void Foo() { ::Foo(1); }
};
In C++, what is the purpose of the scope resolution operator when used without a scope? For instance:
::foo();
It means global scope. You might need to use this operator when you have conflicting functions or variables in the same scope and you need to use a global one. You might have something like:
void bar(); // this is a global function
class foo {
void some_func() { ::bar(); } // this function is calling the global bar() and not the class version
void bar(); // this is a class member
};
If you need to call the global bar() function from within a class member function, you should use ::bar() to get to the global version of the function.
A name that begins with the scope resolution operator (::) is looked up in the global namespace. We can see this by looking at the draft C++ standard section 3.4.3 Qualified name lookup paragraph 4 which says (emphasis mine):
A name prefixed by the unary scope operator :: (5.1) is looked up in global scope, in the translation unit where it is used. The name shall be declared in global namespace scope or shall be a name whose declaration is visible in global scope because of a using-directive (3.4.3.2). The use of :: allows a global name to be referred to even if its identifier has been hidden (3.3.10).
As the standard states this allows us to use names from the global namespace that would otherwise be hidden, the example from the linked document is as follows:
int count = 0;
int main(void) {
int count = 0;
::count = 1; // set global count to 1
count = 2; // set local count to 2
return 0;
}
The wording is very similar going back to N1804 which is the earliest draft standard available.
Also you should note, that name resolution happens before overload resolution. So if there is something with the same name in your current scope then it will stop looking for other names and try to use them.
void bar() {};
class foo {
void bar(int) {};
void foobar() { bar(); } // won't compile needs ::bar()
void foobar(int i) { bar(i); } // ok
}
When you already have a function named foo() in your local scope but you need to access the one in the global scope.
My c++ is rusty but I believe if you have a function declared in the local scope, such as foo() and one at global scope, foo() refers to the local one. ::foo() will refer to the global one.
referring to the global scope