Help describe the process of finding the name x in the last line of the fragment:
struct S { static int x; void f(); };
int S::x;
int x;
void S::f() { x; // <-- }
The name lookup process for an unqualified name in the body of a class member function is described in [basic.lookup.unqual]/8. The following scopes are searched in order:
The block in which the name is referenced, then the enclosing blocks within the same function
The members of the class, then the members of base classes (if any)
The members of the enclosing class or function, then of its base classes if any, then of its enclosing class or function, then of its base classes if any, and so on
The enclosing namespace, then its enclosing namespace, and so on up to the global namespace
Thus, in this case, the body of S::f() is searched first to find a declaration of x; this fails, so a member of class S with name x is then looked for; this finds the static member S::x. The lookup process stops before considering the global scope.
I am not really sure I understand your question, but if you would like to access the global variable x instead of the member x you can use the scope resolution operator ::
void S::f() {
// Assign value of global variable to member x
x = ::x;
// Use the value of the member x
int y = x;
}
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.
#include<iostream>
using namespace std;
int main(){
class c1{
int i;
public:
int bv;
void seti(int i){
c1::i=i;
}
int geti(){return i;}
int accessbv(c1 inst1);
};
int c1::accessbv (c1 inst1){
cout<<"here in the base accesing inst1's bv"<<inst1.bv;
}
I want to access inst1's member variable bv.The above code doesnt compile. What should i do?
Also i have observed one thing ,if the class c1's defintion is global it is working the way i want it to. Why is it behaving this way?
Just because the class is local, doesn't mean the rules for defining functions change. The C++ standard even goes as far as to state it explicitly.
[class.local]/2, emphasis mine:
An enclosing function has no special access to members of the local
class; it obeys the usual access rules (Clause [class.access]). Member
functions of a local class shall be defined within their class
definition, if they are defined at all.
"The rules" mentioned above is simply what is stated in the function definition related section of the standard, [dcl.fct.def.general]/2:
... A function shall be defined only in namespace or class scope.
And that's it.
To expand on StoryTeller's answser here is an example of explaining what it means by your comment to his answer:
can you clarify the first statement "An enclosing function has no special access to members of the local class; it obeys the usual access rules (Clause [class.access])." and add something about no functions allowed inside another function rule.
void someFunc() {
class foo {
private:
int x;
public:
int getX() const { return x; }
void setX( int val ) { x = val; }
};
}
Here foo is a local class that is declared in someFunc(). The scope or body of someFunc has no means of accessing foo's internals. Since the above functions are declared & defined within foo's scope this is valid.
Trying to do this:
void someFunc() {
class boo {
private:
int x;
public:
int getX() const;
void setX( int val );
};
// These are illegal. You can not define a function within a function
// even when they belong to a class.
// These two functions can not be defined here because this is
// considered re-declaring them out side of their class within local scope of a function.
// These will give you a compiler error: local function definitions are illegal
int boo::getX() const { return x; }
void boo::setX( int val ) { x = val; }
}
Results in a compiler error.
Here someFunc() has no way of accessing boo's scope through its scope resolution operator for its member variables. It can not access boo::x.
It is illegal to declare a function within a function this can not be done because of the stack pointer for function scope. Functions are not like while & for loops or switch statements which can be nested. A function's scope is a single translation unit within an object file after it's been compiled. You can have an empty scope within a function as that is valid, but you can not declare - define a function within another.
Here is the corresponding question, what I want to know is, Is it possible to bring global function into the overload resolution with member function?
I tried in 2 ways, but both don't work:
void foo(double val) { cout << "double\n";}
class obj {
public:
using ::foo; // (1) compile error: using-declaration for non-member at class scope
void callFoo() {
using ::foo; // (2)will cause the global version always be called
foo(6.4);
foo(0);
}
private:
void foo(int val) {cout << "class member foo\n"; }
};
I doubt you can make the compiler call one or the other based on the type. You can of course use a local wrapper function, something like this:
void callFoo() {
foo(6.4);
foo(0);
}
private:
void foo(double val) { ::foo(val); }
The wrapper function should nicely inline into nothing, so there is no actual overhead when compiled with optimisation.
Or don't call the member and the global function the same name, which makes life a whole lot easier!
This is plain old unqualified name lookup, specified in §3.4.1 [basic.lookup.unqual]:
1 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.
8 For the members of a class X, a name used in a member function
body, in a default argument, in an exception-specification, in the
brace-or-equal-initializer of a non-static data member (9.2), or in the definition of a class member outside of the definition of X,
following the member’s declarator-id, shall be declared in one of
the following ways:
before its use in the block in which it is used or in an enclosing block (6.3), or
shall be a member of class X or be a member of a base class of X (10.2), or
if X is a nested class of class Y (9.7), shall be a member of Y, or shall be a member of a base class of Y (this lookup applies
in turn to Y’s enclosing classes, starting with the innermost
enclosing class), or
if X is a local class (9.8) or is a nested class of a local class, before the definition of class X in a block enclosing the definition
of class X, or
if X is a member of namespace N, or is a nested class of a class that is a member of N, or is a local class or a nested class within
a local class of a function that is a member of N, before the use of
the name, in namespace N or in one of N’s enclosing namespaces.
Note first that name lookup stops as soon as a declaration is found. So if you have using ::foo; in callFoo(), lookup for foo will end there and never touch the second bullet point; if you don't have it, lookup for foo will find the member foo() at the second bullet point and never search elsewhere. The way unqualified name lookup is specified means that you will either find class members or non-class-members, but never both.
This is also noted in §13.1.1.1 [over.call.func]/p3:
In unqualified function calls, the name is not qualified by an -> or .
operator and has the more general form of a primary-expression. The
name is looked up in the context of the function call following the
normal rules for name lookup in function calls (3.4). The function
declarations found by that lookup constitute the set of candidate
functions. Because of the rules for name lookup, the set of candidate
functions consists (1) entirely of non-member functions or (2)
entirely of member functions of some class T. In case (1), the argument list
is the same as the expression-list in the call. In case (2), the
argument list is the expression-list in the call augmented by the
addition of an implied object argument as in a qualified function
call.
A using-declaration at class scope must name a base class member (§7.3.3 [namespace.udecl]/p3):
In a using-declaration used as a member-declaration, the
nested-name-specifier shall name a base class of the class being defined.
What it appears you are trying to do is use the parameter type to choose the correct overload, and to bring the external foo into your class or member function.
Bringing it into the class is easy. You just declare another overload as a class member that forwards to the external one.
Bringing into the function is tricky but can be done by use of helper functions e.g. fooCaller( double ) and fooCaller( int ) which you can call from callFoo.
If you don't want to expose these to the external user, i.e. hide them away in the cpp file, it can be done but is trickier, due to the fact that foo in your class is private. You would have to have your callFoo function pass in the private function as a member function to "call" for the int overload.
You cannot do that probably because member functions has different signature visible by compiler, which is
void foo(double)
vs
void obj::foo(int)
I don't understand sense of the name used in.... What does it mean? For example (3.4.1/7):
A name used in the definition of a class X outside of a member
function body...
Consider the following example:
class A { static const int a = 4; }
int b = A::a;
The name a after the nested-name-specifier used into the global scope or it used into the class scope?
The namespace analog is defined pretty clear in the 7.3.1/6:
The enclosing namespaces of a declaration are those namespaces in
which the declaration lexically appears, except for a redeclaration of
a namespace member outside its original namespace (e.g., a definition
as specified in 7.3.1.2).
Disclaimer: Warning, language-laywer answer.
What is a "scope"?
Generally, I'd say that a scope is understood as the part of the program text enclosed by {} other than the initializer-brackets. TC++PLv4 p157 "A declaration introduces a name into a scope".
Declarative region
In [basic.scope.declarative]/1, we find the definition of a declarative region:
Every name is introduced in some portion of program text called a declarative region, which is the largest part of the program in which that name is valid, that is, in which that name may be used as an unqualified name to refer to the same entity.
I think we can see the part after "that is" as a definition of the validity of a name.
Scope
[basic.scope.declarative]/1 continues with the definition of scope:
In general, each particular name is valid only within some possibly discontiguous
portion of program text called its scope.
This only defines what the scope of a name is. In the phrases "used in global scope" or "used in the scope of the class", the term scope is used not related to a specific name. Similarly, [basic.scope.declarative]/3
The names declared by a declaration are introduced into the scope in which the declaration occurs, except [...].
Here, the term scope is also used in that second meaning, unrelated to a specific name.
Defining the second meaning of "scope"
Several language features such as block statements, namespaces and classes introduce a new scope. E.g. [stmt.block]/1
A compound statement defines a block scope.
Scope in its second meaning is used at least in three different contexts:
looked up in the scope of X
used in the scope of X
is in the scope of X
Looked up in the scope of X
Example: 3.4.3/1
If the nested-name-specifier of a qualified-id nominates a class, the name specified after the nested-name-specifier is looked up in the scope of the class, except for the cases listed below.
class X
{
int m;
void foo() { int n; }
};
decltype(X::m) v; // legal
decltype(X::n) w; // illegal
In this context, the scope of class X does not extend to any nested scopes such as member functions or nested classes.
Used in the scope of X
Example: 3.3.7/2
The name of a class member shall only be used as follows:
in the scope of its class (as described above) or a class derived from its class,
[...]
class X
{
int m;
void foo()
{
decltype(m) n;
}
static int o;
};
int X::o = decltype(m)();
Here, the scope of class X extends to nested scopes and other parts of the program, such as definitions of members outside of the class body.
Note that the initializers of static data members, nested classes and local classes are explicitly defined to be in the scope of wherever the static data member / class has been declared. For member functions, I can only find non-normative notes such as 9.3/5
The member function f of class X is defined in global scope; the notation X::f specifies that the function f is a member of class X and in the scope of class X.
As I understand it, this "is in the scope of" for member functions and nested/local classes says that those newly introduced scopes are nested scopes.
"Used in the scope of X" does not occur very often in the Standard. One could argue that 3.3.7/2 should be extended to nested scopes, to make "used in the scope of" consistent with "looked up in the scope of".
To be in the scope of X
Example: 8.5/13
An initializer for a static member is in the scope of the member's class.
class X
{
static int m;
static int n;
};
int n;
int o;
int X::m = n; // X::n
int X::n = o; // ::o
Name lookup for unqualified names searches the scopes (plural) "in the order listed in each of the respective categories" [basic.lookup.unqual]/1. For the initializers of the two static data members, the scope of class X is searched first, then any base classes, then the enclosing scope (here: the global scope), [basic.lookup.unqual]/7.
What is meant with "to be in the scope of X" seems to me that for unqualified lookup, the scopes searched are the ones that are searched for names used inside X, maybe plus access rules (initializers of static data members may access private members etc). As said above, this effectively nests scope of member functions and nested classes defined outside their enclosing class' body in the scope of that enclosing class.
Trying to define the scope of X
Not including the weird extensions of "used in the scope of X".
3.3.3 to 3.3.9 categorize various kinds of scopes of names. We can use these categories to categorize the parts of our program where names can be declared: A part of a program where names with block scope can be declared is a block scope. A part of the program where names with class scope can be declared is a class scope. We still need to differentiate different scopes of the same kind:
void foo()
{ // begin scope A
int a; //
{ // begin scope B
int b; //
int c; //
} // end scope B
int d; //
} // end scope A
The Standard calls A an outer scope of B (in name lookup). However, the scope B is not part of the scope A. Maybe something like "B is in the scope of A, but the names declared inside B are not in the scope of A". Consider:
class A
{
int m;
class B
{
int n;
};
};
Here, name lookup "in the scope of the class A" won't find members of the nested class B with unqualified lookup. Also relevant: anonymous unions.
I think the best way to perform this separation is to look at the individual language features which can introduce a scope. For example, [stmt.block]/1 "A compound statement defines a block scope." We can then look at any part X of the program, find the closest previous language feature that introduced a scope which has not ended yet(*), take all the regions of the program where newly declared names are in the same scope (**), and call this the enclosing scope of X.
(*) not ended yet: for a block, the end of the block etc. (i.e., as specified by the language feature) Alternatively, not ended yet = where a name could have been declared that is still valid
(**) in the same scope: searching, beginning from this new declaration, the closest previous language feature that introduced a scope which has not ended yet, shall find the same part of the program
This seems to comply with what has been intended as the definition of declarative region as used in [basic.scope.declarative]/4:
Given a set of declarations in a single declarative region, each of which specifies the same unqualified name, they shall all refer to the same entity, or [... = be function overloads], or [... = various exceptions].
This, as far as I can see, contradicts the definition given in [basic.scope.declarative]/1:
int main()
{
int x;
{
int x;
}
}
Here, we have two declarations specifying the same unqualified name. The outer x as a name is valid also inside the inner {}; yet, this is a perfectly legal C++ program. I suspect that declarative region in fact shouldn't be associated with a single name.
I think it is possible to simplify this definition of scope by using the terminals { and }.
This phrase
A name used in the definition of a class X outside of a member
function body...
considers all names that are used in the definition of a class that is starting from the class head and ending in the closing brace excluding names used in member functions (names used in member functions are considered in other paragraph).
For example
class B : public A
{
int x;
int a[i];
C z;
//..
};
So these names are A, x, a, i, C, z.
Take into account that though names x, a, and z are defined in the class their names can be used in other member definitions of the class.
As for your code example
class A { static const int a = 4; }
int b = A::a;
The name a after the nested-name-specifier used into the global scope or it used into the class scope?
then name a is searched in the class scope of class A but its qualified name used in the global scope to initialize variable b.
Consider another example though it has nothing common with the phrase you cited but has a relation with your code.
struct A
{
static int a;
static int b;
};
int A::a = 10;
int A::b = a;
Here is used name a without nested name specifier. It is one more rule how names are searched in the class scope.
There is a quote described name lookup applied to data member of a const static data member after the quialified-id of the data member:
sec. 3.4.1/13:
A name used in the definition of a static data member of class X
(9.4.2) (after the qualified-id of the static member) is looked up as
if the name was used in a member function of X.
But we can define in-class static const data member:
class A
{
static const int i = x;//x is a name defined an arbitrary const int
};
Rule from the sec. 3.4.1/13 does not apply to the name x lookup. What rule will be applied actually? Please give a reference to a corresponding clause from standard.
For instance, the following code is valid:
#include <stdio.h>
const int a=5;
class A
{
public:
static const int b=a;//b is unqualified-id of this data-member
};
int main(){ printf("%d\n",A::b); } //5
The following code is also valid:
#include <stdio.h>
class A
{
public:
static const int a=7;
static const int b=a;
};
int main(){ printf("%d\n",A::b); } //7
But the following is invalid:
#include <stdio.h>
class A
{
public:
static const int b=a; //error: a was not declare in this scope.
static const int a=7;
};
int main(){ printf("%d\n",A::b); }
It is unclear what rules applied to lookup of a.
An in-class declaration of a static data member is not a definition even if it includes an initializer. Therefore §3.4.1/13 does not apply to your example.
Name lookup in class scope is defined by the rules of which scopes reach a class scope. §3.3.7/1.1:
The potential scope of a name declared in a class consists not only of the declarative region following the name’s point of declaration,
but also of all function bodies, default arguments,
exception-specifications, and brace-or-equal-initializers of
non-static data members in that class (including such things in nested
classes).
A name N used in a class S shall refer to the same declaration in its context and when re-evaluated in the completed scope of S. No
diagnostic is required for a violation of this rule.
If reordering member declarations in a class yields an alternate valid program under (1) and (2), the program is ill-formed, no
diagnostic is required.
The purpose of these rules is to allow a member function to access member variables that are declared later in the class. Because the rules don't mention initializers of static data members, name lookup from a static data member defaults to 3.4.1/7:
A name used in the definition of a class X outside of a member
function body, default argument, exception- specification,
brace-or-equal-initializer of a non-static data member, or nested
class definition shall be declared in one of the following ways:
The list essentially boils down to "a name must be a member of the same class, or declared in an enclosing scope." In your first example, a is declared in the enclosing namespace, so it is found. In the second example, a is declared before it is used.
But in the third example, it is used before it is declared which is illegal — and if there was a declaration of some a in the enclosing namespace, it would be undefined behavior due to 3.3.7/1.2.
#include <stdio.h>
const int a=5;
class A
{
public:
static const int b=a; // The quote corresponds to the lookup for a.
// It says that the lookup logic for a is the same
// as the lookup for a name in a member function of A
};
If you have member function, let's make it static for easy comparison, let's see what the lookup for a name in the function looks like.
class A
{
public:
static void fun()
{
b = a;
// The lookup for a:
// 1. A local variable in the function.
// 2. A `static` member of the class.
// 3. A variable in the enclosing namespace.
}
static const int b;
};
When you use
static const int b = a;
the lookup for a will be (2) and (3) from the function foo since a cannot be a local variable.