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.
Related
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;
}
Referring to this code:
namespace Y {
char f() { return y; } // error: y was not declared in this scope
char y;
}
struct X {
char f() { return x; } // OK
char x;
};
As per basic.scope.namespace#1:
The declarative region of a namespace-definition is its
namespace-body. Entities declared in a namespace-body are said to be
members of the namespace, and names introduced by these declarations
into the declarative region of the namespace are said to be member
names of the namespace. Its potential scope includes its namespace from the name's point of declaration onwards.
QUESTIONS
Is it correct to say that the error was due to the fact that Y::y is not yet declared in Y::f()?
I can't figure why there isn't a "reodering" for namespace members during declaration while for struct there is. What could be the reason for disallowing such behavior? Does the standard says something similar?
Is it correct to say that the error was due to the fact that Y::y is not yet declared in Y::f()?
Yes.
I can't figure why there isn't a "reodering" for namespace members during declaration while for struct there is. What could be the reason for disallowing such behavior? Does the standard says something similar?
The biggest hindrance for namespaces as opposed to classes, is that they are never "closed". You can always add members to a namespace by re-opening it in another translation unit and declaring more stuff in it. A class declaration however, for all its members, must appear entirely in a single translation unit. And there is no adding to it later.
[class.mem]/1
The member-specification in a class definition declares the full set
of members of the class; no member can be added elsewhere.
The problem for namespaces is intractable. But classes only require a little more, quite localized, work.
It is therefore much easier, both to a language designer and a compiler writer, to demand namespace declarations appear before they are used.
You should also note that you can only use other members of the class in only a specific set of places inside the definition.
[class.mem]/6
A class is considered a completely-defined object type ([basic.types])
(or complete type) at the closing } of the class-specifier. Within the
class member-specification, the class is regarded as complete within
function bodies, default arguments, noexcept-specifiers, and default
member initializers (including such things in nested classes).
Otherwise it is regarded as incomplete within its own class
member-specification.
You are mistaken thinking that for structures there is "reordering".
Consider the following structure definition.
#include <iostream>
struct A
{
char s[N];
enum { N = 10 };
};
int main()
{
return 0;
}
The compiler will issue an error because the name N is not yet declared when it is used in the array declaration. So neither "reordering" exists in the class scope. As for member functions then names used within a member function are at first searched in the class scope.
Moreover a name declared in a namespace can hide the same name declared in the outer namespace. As result the "reordering" breaks scopes of variables.
namespace libzerocoin {
//Commitment class
Commitment::Commitment::Commitment(const IntegerGroupParams* p,
const Bignum& value): params(p), contents(value) {
this->randomness = Bignum::randBignum(params->groupOrder);
this->commitmentValue = (params->g.pow_mod(this->contents, params->modulus).mul_mod(
params->h.pow_mod(this->randomness, params->modulus), params->modulus));
}
I just encountered this function definition on GitHub.
I assume that the second and the third "Commitment" refer to the class name and constructor, but I can't figure out the meaning of the first. I am sure that it does not refer to the namespace because that name is different. I have seen the scope resolution operator being used twice in examples, but those refer to nested namespaces.
In C++ classes have the feature of having their name injected into their scope ([class]/2):
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.
And the code snippet you showed makes use of it. In certain contexts Commitment::Commitment names the class itself, and in others names the c'tor. Only the last Commitment(, where you open the parentheses, begins the c'tor definition.
And it can look much much worse:
struct foo {
foo();
};
foo::foo::foo::foo() = default;
Which you can see is valid C++ Live.
I am unsure if the two data member declarations in class B are equivalent.
//file0.h
namespace C
{
typedef int Id;
}
//file1.h
namespace A
{
typedef int Id;
}
//file2.h
namespace A
{
class B
{
public:
// ...
//Want to add data member theId as:
//Id theId;
//or
//A::Id theId;
}
}
That is, in the absence of A::, is there a default namespace the C++ standard uses in cases like this one? e.g., it may default to namespace A because the class is being declared in it.
If one uses Id theId, which namespace would it use, A or C?
Edit 1: Commented out code to avoid confusion.
Edit 2: Added another "theId" with a different namespace to illustrate better the question.
Answer is Id results in A::Id theId.
Why?
Id (without the A::) is an unqualified name. C++ then resorts to this rule to find the right Id:
Member function definition For a name used inside a member function
body, a default argument of a member function, exception specification
of a member function, default member initializer, or inside a nested
class definition (including names of the bases from which the nested
class is derived), the scopes searched are the same as in class
definition,[...]
[Class definition] the following scopes are searched:
d) 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.
Reference: http://en.cppreference.com/w/cpp/language/unqualified_lookup
If you go to the accepted answer of this post
Could someone please elaborate on why he uses:
double temp = ::atof(num.c_str());
and not simply
double temp = atof(num.c_str());
Also, is it considered a good practice to use that syntax when you use "pure" global functions?
It says use the global version, not one declared in local scope. So if someone's declared an atof in your class, this'll be sure to use the global one.
Have a look at Wikipedia on this subject:
#include <iostream>
using namespace std;
int n = 12; // A global variable
int main() {
int n = 13; // A local variable
cout << ::n << endl; // Print the global variable: 12
cout << n << endl; // Print the local variable: 13
}
:: is the scope resolution operator. Its use in this scenario, as a unary operator, is to ensure that the name (atof) is always looked up in the global scope -- this can be useful to prevent name hiding from interfering with the lookup.
The :: operator is scope resolution operator.
when used with class specifier as like A::a, it is to access the data memeber a of the class A.
when used without any specifier, it access the global variable.
It is used mainly in the following contests.
To refer to the global variables.
To refer to the static members of the class
To avoid ambiguites, when a class inherits from multiple [ non-virtual
base ] classes.
With using directive, to use the base class functions in the derived class, when there is a function in base class with name same as that of the derived class, but for a different type.
To access the functions defined in the global scope, when you have a function defined with the same signature, as in double temp = ::atof(num.c_str());
To create objects of the nested classes.
Lets say you have two versions of a function f() one defined outside a namespace and one defined inside. Now lets say you have one more function g() in the same namespace. Now if you do f() inside g() it will call the one defined in the same namespace. But if you want to call the global version you need to do ::f()
::func() means that this function is not affiliated with any specific class. It is used when there exist many functions with the same name, and to avoid confusion between the one you want and specific member functions you precede the function name with the scope operator.
From C++ Primer, 4th edition, section 17.2.1:
"Names defined at global scope - names declared outside any class, function, or namespace - are defined inside the global namespace. The global namespace is implicitly declared and exists in every program. Each file that defines entities at global scope adds those names to the global namespace.
The scope operator can be used to refer to members of the global namespace. Because the global namespace is implicit, it does not have a name; the notation
::member_name
refers to a member of the global namespace."