I don't understand 3.4/2 in the Standard - c++

I don't understand 3.4/2 in the Standard:
A name “looked up in the context of an expression” is looked up as an
unqualified name in the scope where the expression is found.
What if the name is qualified, as N::i below?
#include <iostream>
namespace N { int i = 1; }
int main()
{
int i = 0;
std::cout << N::i << '\n';
}
The qualified name N::i is not looked up in the scope where N::i is found, i.e., it's not looked up in the scope of main() and the global scope!

To expand on the comment by #JerryCoffin, the rules for qualified lookup are:
3.4.3 Qualified name lookup [basic.lookup.qual]
3 In a declaration in which the declarator-id is a qualified-id, names
used before the qualified-id being declared are looked up in the
defining namespace scope; names following the qualified-id are looked up
in the scope of the member’s class or namespace.
Here's an example:
#include <iostream>
struct N { enum { i = 1 }; };
int main()
{
std::cout << N::i << '\n'; // prints 1
struct N { enum { i = 0 }; };
std::cout << N::i << '\n'; // prints 0
}
Live Example.

First the left-hand side of :: is looked up, and then the right-hand side is looked up inside it. So, to look up N::i, first it finds N using unqualified lookup, then it looks inside N to find i. Simple!
In your example, you redefine N locally. After the local definition, the outer definition is hidden per §3.3.10: "A name can be hidden by an explicit declaration of that same name in a nested declarative region or derived class."
Since the compiler knows at the outset that the left-hand side (N) must yield a type, namespace, or enumeration, any other lookup results (i.e. functions, variables, and templates) are ignored. So, you could also do:
#include <iostream>
struct N { enum { i = 1 }; };
int main()
{
int N = 3;
std::cout << N::i << '\n'; // prints 1
std::cout << N << '\n'; // prints 3
struct N { enum { i = 0 }; };
std::cout << N::i << '\n'; // prints 0
}
http://coliru.stacked-crooked.com/a/9a7c9e34b1e74ce7
See §3.4.3/1:
The name of a class or namespace member or enumerator can be referred to after the :: scope resolution operator (5.1) applied to a nested-name-specifier that denotes its class, namespace, or enumeration. If a :: scope resolution operator in a nested-name-specifier is not preceded by a decltype-specifier, lookup of the name preceding that :: considers only namespaces, types, and templates whose specializations are types. If the name found does not designate a namespace or a class, enumeration, or dependent type, the program is ill-formed.

Related

Code displays "::" on the terminal, cause unknown

using namespace std;
struct A
{
int i;
A(int i_ = 13) : i(i_)
{
cout << _FUNCTION_ << "\n";
}
~A()
{
cout << _FUNCTION_ << "\n";
}
};
int main()
{
A* p = new A;
A a();
return 0;
}
When I run it, the code displays on my terminal "A::A". I get that the first A is called from first FUNCTION for "A* p" , but why does "::" appear? And the last A after "::" is from " A a(); "?
A constructor for a type has the same name as the type itself. :: is the scope resolution operator and is used to name things contained within a named scope, such as a namespace or a type.
The constructor of A is therefore A::A. The first A is the name of the type, and the second is the name of the constructor; the :: is to indicate that the constructor is declared within the scope of the type.
This mirrors the way you would define type members following a declaration with no definition. For example:
struct A
{
int i;
A(int i_ = 13);
~A();
};
// Note how we have to refer to the constructor to define it since we are
// no longer within the scope of A:
A::A(int i_) : i(i_)
{
cout << _FUNCTION_ << "\n";
}
// Similar for the destructor.
A::~A()
{
cout << _FUNCTION_ << "\n";
}
You should only see A::A in your output. Note that you only create one A value here:
A* p = new A;
You never delete p; and so you don't see the matching destructor call (A::~A) in the output.
This line does not create a variable of type A; rather, it declares a function called a that takes no arguments and returns an A value. This function is never invoked (nor defined):
A a();
This is a vexing parse (not to be confused with the most vexing parse). Clearly you intended to declare a variable, but this could be either a function or variable declaration, and the grammar prefers a function declaration.
To fix this, either remove the parens or use C++11's uniform initialization syntax:
A a; // Default initialization
A a{}; // Uniform initialization
_FUNCTION_ is a magic constant, therefore it posts the first "A" (name of the function called. Can't help with the rest though.

Static variable shadowing global

I am trying to create an object using placement new (I know to use smart pointers, this is just to learn). My code is as follows:
#include <vector>
#include <iostream>
#include <memory>
using namespace std; // please excuse this
// if you change like 19 to arr1 (or any other var name) instead of arr and line 40 to arr1 then it works
struct A
{
int in = 999;
A()
{cout << "A ctor\n";}
~A()
{cout << "A dtor\n";}
};
char arr[sizeof(A)];
class B
{
public:
static char arr[sizeof(A)];
const static A* a_obj;
B()
{
cout << "B ctor\n";
//cout << (a_obj->in) << endl;
}
~B()
{
cout << "B dtor\n";
}
};
const A* B::a_obj = new(arr) A;
int main()
{
B g;
}
I have created a global array named arr and another array named arrin B. It seems like when I do my placement new the arr being used is from the class as I get what I think are linker errors.
Why is this happening? why isn't the global arr being used? If i change the placement new to use my renamed global array it works. I think it has to do something with lookups but I don't have a concrete answer.
From the C++ 2017 Standard (12.2.3.2 Static data members)
2 The declaration of a non-inline static data member in its class
definition is not a definition and may be of an incomplete type other
than cv void. The definition for a static data member that is not
defined inline in the class definition shall appear in a namespace
scope enclosing the member’s class definition. In the definition at
namespace scope, the name of the static data member shall be qualified
by its class name using the :: operator. The initializer expression
in the definition of a static data member is in the scope of its
class (6.3.7).
So in this definition of the static data member
const A* B::a_obj = new(arr) A;
the unqualified name arr is at first searched in the scope of the class B. And the class B indeed declares such a name
static char arr[sizeof(A)];
If you want to use the name from the global namespace then use the qualified name
const A* B::a_obj = new(::arr) A;
Here is a demonstrative program
#include <iostream>
struct A
{
const static int N = 10;
static int n1;
static int n2;
};
const int N = 20;
int A::n1 = N;
int A::n2 = ::N;
int main()
{
std::cout << "A::n1 = " << A::n1 << std::endl;
std::cout << "A::n2 = " << A::n2 << std::endl;
return 0;
}
Its output is
A::n1 = 10
A::n2 = 20
The reason arr is attribute to the class B and not the global scope is due to unqualified name lookup rules.
Specifically:
Static data member definition For a name used in the definition of a
static data member, lookup proceeds the same way as for a name used in
the definition of a member function.
Meaning:
struct X {
static int x;
static const int n = 1; // found 1st
};
int n = 2; // found 2nd.
int X::x = n; // finds X::n, sets X::x to 1, not 2
If you are intrested you can see more information here:
http://en.cppreference.com/w/cpp/language/unqualified_lookup
As people suggested to get what you want just use:
const A* B::a_obj = new(::arr) A;

initializer_list and argument-dependent lookup

I'm trying to use an std::initializer_list as an argument in a function that uses argument-dependent lookup (ADL). But I don't get it to work and I don't understand why. The following is a minimal failing example:
#include <initializer_list>
#include <iostream>
class Foo {
public:
inline friend void bar(std::initializer_list<Foo> v) {
std::cout << "size = " << v.size() << std::endl;
}
};
void baz(std::initializer_list<Foo> v) {
std::cout << "size = " << v.size() << std::endl;
}
int main(){
Foo a;
//bar({a,a}); // error: use of undeclared identifier 'bar'
baz({a,a}); // works
return 0;
}
As seen above, an equivalent global function works just fine. Why does the above not work?
I'm using clang on OS X 10.10.
I believe that the problem is that the subexpression1 { a, a } does not really have a type, and as such it does not have associated types or namespaces which in turn means that ADL does not kick in. If you have a function in the global namespace, normal lookup will find it, and it will find that { a, a } can match the function call as the initializer for std::initializer_list<Foo>.
1 The syntax { a, a } is called braced-init-list and it is not really an expression (or subexpression) in the language.
When the compiler sees bar({a,a}), it doesn't know the type of the arguments, so it searches for bar in the global namespace (::), and nowhere else. If you changed that line to Foo{a,a}, then it knows the argument is a Foo, and so also searches the Foo class for functions.

Overloading function doesn't work with complex

I have written this simple C++ code to swap any two variables. It works for int and double, but doesn't work for complex numbers, any idea why?
#include <iostream>
#include <complex>
using std::cout;
using std::endl;
using std::complex;
template <class T>
inline void swap(T& d, T& s)
{
T temp = d;
d = s;
s = temp;
}
int main()
{
int m=5, n=10;
double x=5.3, y=10.6;
complex<double> r(2.4, 3.5), s(3.4, 6.7);
cout << "inputs: " << m << " , " << n << endl;
swap(m, n);
cout << "outputs: " << m << " , " << n << endl;
cout << "double inputs: " << x << " , " << y << endl;
swap(x, y);
cout << "double outputs: " << x << " , " << y << endl;
cout << "complex inputs: " << r << " , " << s << endl;
swap(r, s);
cout << "complex outputs: " << r << " , " << s << endl;
}
This is the error:
g++ 02.swap.template.cpp -o c.out.02
02.swap.template.cpp: In function ‘int main()’:
02.swap.template.cpp:37:13: error: call of overloaded ‘swap(std::complex<double>&, std::complex<double>&)’ is ambiguous
02.swap.template.cpp:37:13: note: candidates are:
02.swap.template.cpp:13:13: note: void swap(T&, T&) [with T = std::complex<double>]
/usr/include/c++/4.6/bits/move.h:122:5: note: void std::swap(_Tp&, _Tp&) [with _Tp = std::complex<double>]
name conflit, changing to ::swap solves the issue.
The problem is that argument-dependent lookup is applied because you are calling a function template. If you had a plain function, there would be no ambiguity:
#include <complex>
void swap(complex<double> & d, complex<double> & s)
{
complex<double> temp = d;
d = s;
s = temp;
}
int main()
{
std::complex<double> r(2.4, 3.5), s(3.4, 6.7);
swap(r, s);
}
This is because of C++11 3.4.2:
Let X be the lookup set produced by unqualified lookup (3.4.1) and let Y be the lookup set produced by argument dependent lookup (defined as follows). If X contains
— a declaration of a class member, or
— a block-scope function declaration that is not a using-declaration, or
— a declaration that is neither a function or a function template
then Y is empty. Otherwise Y is the set of declarations found in the namespaces associated with the argument types as described below. The set of declarations found by the lookup of the name is the union of X and Y.
In the above case, X contains a block-scope function declaration.
However, if the unqualified lookup finds the function template you provided, then the ADL rules say that the argument-dependent lookup set is also considered. Since std::complex<double> lives in the std namespace, this namespace is also searched for the name swap, which already exists (by 20.2.2).
You can prevent argument-dependent lookup by wrapping the function name in parentheses:
(swap)(r, s);
This way, only the unqualified lookup is considered.
The compiler says it is confused because of two functions : yours and the standard std::swap. It consider std::swap too because std::complex is member of std::namespace, it's calling Argument Dependant Lookup. If you want to explicitly test your swap, you can use :: scope resolution operator, ie ::swap instead of swap. It will make another kind of lookup : Qualified Name Lookup solving the ambiguity.
Nonetheless, std::swap works well and do the job, except as exercise, include utility standard header, make a using std::swap, and it will work fine :
#include<utility>
//before needed (closest)
using std::swap;
swap(/*arguments*/);

Order of evaluation of names declared in class

There is this code:
#include <iostream>
const int c = 3;
struct A {
static int f() { return c; }
static const int c = 2;
};
int main() {
std::cout << A::f() << std::endl; // 2
return 0;
}
How does it happen that variable c defined inside class A is used in function f instead of variable c defined in global scope although global variable c is declared first?
It does not matter which variable is declared first: if a class has a variable with the same name in it, that variable trumps the global variable. Otherwise you could get existing code in a lot of trouble simply by declaring a global variable with a name of one of its member variables!
Of course your class can use scope resolution operator to reference the global c directly:
static int f() { return ::c; }
Now your program will print 3 instead of 2.
Is not a question of declaring order but of variable scope, the used variable are searched before in the current method/function after in the class/struct and a the and in the global context,
example:
#include <iostream>
const int c = 3;
struct A {
static void print() {
int c = 4
std::cout <<"Method Scope:"<< c << std::endl; // 4
std::cout <<"Class/Struct Scope:"<< A::c << std::endl; // 2 here you can use alse ::A::c
std::cout <<"Global Scope:"<< ::c << std::endl; // 3
}
static const int c = 2;
};
struct B {
static void print() {
std::cout <<"Method Scope:"<< c << std::endl; // 2
std::cout <<"Class/Struct Scope:"<< B::c << std::endl; // 2 here you can use alse ::A::c
std::cout <<"Global Scope:"<< ::c << std::endl; // 3
}
static const int c = 2;
};
struct C {
static void print() {
std::cout <<"Method Scope:"<< c << std::endl; // 3
//std::cout <<"Class/Struct Scope:"<< C::c << std::endl; //is inpossible ;)
std::cout <<"Global Scope:"<< ::c << std::endl; // 3
}
};
int main() {
A::print();
B::print();
C::print();
return 0;
}
imagine that you have long code which uses many variables, do you want them to be called instead these from a class to which function belongs? stating:
a or b
in class means
this->a
this->b
and if you want global variable to be visible you have to use it like
::a or ::b inside this function, so via:
static int f() { return ::c; }
From the standard docs, Sec 3.3.1
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. In general, each particular name is valid only within some possibly discontiguous portion of program text
called its scope. To determine the scope of a declaration, it is sometimes convenient to refer to the potential scope of
a declaration. The scope of a declaration is the same as its potential scope unless the potential scope contains another
declaration of the same name. In that case, the potential scope of the declaration in the inner (contained) declarative
region is excluded from the scope of the declaration in the outer (containing) declarative region.
this means that the potential scope is same as the scope of the declaration unless another (inner) declaration occurs. If occurred, the potential scope of the outer declaration is removed and just the inner declaration's holds, so your global variable is hidden.