Why do some of these compile and some not compile?
Scenario 1: compilation error 'main' : redefinition; previous definition was 'data variable'
#include <iostream>
using namespace std;
int main;
int main(){ }
Scenario 2: compilation error syntax error : missing ';' before identifier 'obj
#include <iostream>
using namespace std;
class main { };
int main(){
main obj;
}
Scenario 3: working fine
#include <iostream>
using namespace std;
class main { };
int main(){
class main obj;
}
Scenario 4 : working fine
#include <iostream>
using namespace std;
class main {};
main obj;
int main(){ }
Name lookup works in terms of names. The name is looked up, independent of what that name designates.
It's not permitted for the same name to be declared as both a function and a variable, in the same scope.
However, it is permitted for class X to exist even if X is the name of a function or a variable. When you have class X, then the current scope gets X as a name (designating that class). If the same scope has X declared as both a typename and a variable name, then just looking up x finds the variable name.
If a new scope declares X then any use of X in that scope finds the name declared in its scope, this is called shadowing. (Name lookup searches the current scope, then the scope which enclosed that, and so on up to the global scope).
Error, attempts to declare main as both a function and a variable
To process main obj;, the name main is looked up. The current scope is checked first, and it finds the function name main; so it does not check the global scope. We say that the inner scope's name shadows the outer scope's name. So, it is the same error as you would get from void foo(); foo obj;
class main unambiguously says to look up the class name main; that does not find int main() so it falls back to checking the global scope.
nothing new, main obj; makes no difference .
Another interesting example would be:
int x;
class x { };
int main()
{
x = 1; // ok
x y; // error, `x` means the int
class x y; // ok
}
Related
Here is the code example:
namespace A
{
int k;
}
void k(int,int){/*dosomething*/}
int main()
{
using namespace A;
k(1,1);//ooop!k is ambiguous!
}
What happened? I thought it should not be ambiguous since they are different types. Why is it ambiguous? With int k it is not possible to do k(1,1).
So it has nothing to do with what the name actually is?Even if a name that is not a function type will also cause ambiguity when we use k(1,1) ,which is wrong in grammar because int k is not function?
Lookup of the name k is ambiguous because there are two matching declarations visible, ::k and ::A::k .
The exact rule can be found in the C++ Standard (N4659 [basic.lookup]/1):
Name lookup associates the use of a name with a set of declarations of that name. The declarations found by name lookup shall either all declare the same entity or shall all declare functions; in the latter case, the declarations are said to form a set of overloaded functions.
Looking up an unqualified name that is used for a function call has two stages:
Unqualified lookup of the name
Argument-dependent lookup of the name.
The unqualified name lookup rules, even when looking up a name that is being used for a function call, find any declaration of that name. (The rule is NOT that it only searches for function declarations of that name). This stage finds both ::k and ::A::k regardless of whether those are functions, ints, or whatever.
The argument-dependent lookup does have a rule that only function declarations are found for that part of the lookup. But that is not relevant to this code.
The relevant behaviour of the using directive is covered by [basic.lookup.unqual]/2 (edited by me to just show the parts relevant to this question):
For the purpose of the unqualified name lookup rules, the declarations from the namespace nominated by the using-directive are considered members of that enclosing namespace.
This clarifies that using namespace A; does not actually introduce the members of A into the scope of main(); but it means that when looking up a name in the global namespace (because that is the innermost enclosing namespace of the site of the using declaration), the names from A will also be found there.
There are three ways to resolve the ambiguity:
1st:
int main() {
A::k = 5;
::k( 1, 1 );
}
2nd:
int main() {
using namespace A;
A::k = 5;
::k(1, 1);
}
3rd:
namespace A {
int k;
}
namespace B {
void k( int, int ) { /* do something */ }
}
int main() {
using namespace A or B but not both!
if A then k = 5; okay && k(1,1); error
if B then k(1, 1); okay && k = 5; error
if both again ambiguous unless A::k = 5; || B::k(1,1);
return 0;
}
Due to the nature of ambiguity it doesn't truly pay to use using namespace A. And this is why it is considered bad practice to have using namespace std; either in the global scope or directly in the main function. It is okay to use it in a function or a member function of a class/struct as long as you don't conflict with any other library.
I ran this in my IDE visual studio 2017 CE and here is the compiler error:
1>------ Build started: Project: ChemLab, Configuration: Debug Win32 ------
1>main.cpp
1>c:\...\visual studio 2017\projects\chemlab\chemlab\main.cpp(17): error C2872: 'k': ambiguous symbol
1>c:\...\visual studio 2017\projects\chemlab\chemlab\main.cpp(8): note: could be 'void k(int,int)'
1>c:\...\visual studio 2017\projects\chemlab\chemlab\main.cpp(6): note: or 'int A::k'
1>Done building project "ChemLab.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
When you use the using namespace directive it will take everything that is in that namespace and make it visible to main. So now in main you have both the namespace A and the global namespace visible within main. Since you have both visible you now have 2 identifiers or symbols in the look up table named k. And when you call k(1, 1) it doesn't know which one you intended to choose.
This is no different than doing this:
main.cpp
#include <string>
class string {
public:
char* _chars;
};
int main() {
using namespace std;
string myString; // error ambiguous did you mean ::string or std::string?
return 0;
}
This might provide you with some more insight:
When the using directive is being used, don't think of the variable k and the function k as being declared in the same scope. They were previously declared in their own scope. The variable k is in ::A::k and the function void k(int,int){} is in ::k(int,int){}. In the main function when you apply the using namespace A; what happens here it takes every symbol after A:: and it kind of shifts it as if it were in the global :: scope for visibility. Now the compiler has to make a choice on the available symbols and sees I have a k and a k. Did you mean int k(){} or void k(int,int){}...
The ambiguity comes from the name. There is no way to overload a variable like you would a function/method, so there is a "clash" in the names.
In order to get the "k" that you want, you need to specify the namespace.
namespace A
{
int k;
}
void k(int, int) {/*dosomething*/ }
int main()
{
using namespace A;
::k(1, 1); // uses the global namespace
A::k = 5; // uses the namespace A
}
Or, to take the namespace out of the equation:
void k(int, int) {/*dosomething*/ }
void k(int, int, float) {}
int main()
{
int k;
// all of these are now ambiguous
k(1, 1);
k(1, 2, 0.4);
k = 5;
}
I was testing the name lookup rules for C++. I've got a simple program having 3 files:
$cat testns01.h
struct S{
static int f(){return 1;}
};
$cat testns02.h
namespace S{
static int f(){return 2;}
}
$cat testns3.cpp
#include "testns02.h" // namespace
#include "testns01.h" // struct
#include<stdio.h>
int main()
{
int i = S::f();
printf("%d\n",i);
return 0;
}
If I compile and run, I get:
$g++ testns3.cpp && ./a.out
1
OK, I have 3 questions:
name "S" duplication between class name and namespace doesn't conflict?
When both has name "S", seems "struct S" has higher priority
If I comment the line of #include "testns01.h", the program will print 2, still OK. So my third question is:
Does the c++ standard talk about how name lookup resolves duplicated name duplication?
name "S" duplication between class name and namespace doesn't conflict?
They do.
When both has name "S", seems "struct S" has higher priority
It doesn't. (look below)
Does c++ stardard talke about how name lookup resolves duplicated name duplication?
Yes. Quoting the relevant part of N4140:
§3.3.1 [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 all refer to functions and function templates; or
exactly one declaration shall declare a class name or enumeration name that is not a typedef name and the other declarations shall all
refer to the same variable or enumerator, or all refer to functions
and function templates; in this case the class name or enumeration
name is hidden. [ Note: A namespace name or a class template name
must be unique in its declarative region. —end note ]
I think you accidentally got your example working for you, because you repeated the include guards. I was able to reproduce the "preference" for class S from the question:
#ifndef FOO
#define FOO
struct S{
static int f(){return 1;}
};
#endif
#ifndef FOO
#define FOO
namespace S{
static int f(){return 2;}
}
#endif
#include<stdio.h>
int main()
{
int i = S::f();
printf("%d\n",i);
return 0;
}
link
I want to have functions with the same name but using different namespace. I have declared a function in a namespace:
GPS.cpp
namespace NSpace_IMUandGPS
{
//Read GPS Data Set Raspberry Pi's Time and date
void ReadGPS(FD &Fd, bool &GPSready, bool &TimeConfigured, S_POS &POS, S_GPS&GPS, S_IMU &IMU, double &Velocity)
{
...
}
}
GPS.h
namespace NSpace_IMUandGPS
{
void ReadGPS(FD &Fd, bool &GPSready, bool &TimeConfigured, S_POS &POS, S_GPS &GPS, S_IMU &IMU, double &Velocity);
}
MAIN.cpp
I want to use this function in main with structures that are not declared in NSpace_IMUandGPS namespace. So, how should I do this? If I declare the function in a namespace, Do all the variables have to be defined in the same namespace?
You can address a namespace using the :: operator.
Syntax: namespace::function();
So in case you wannt to you, in example the std namespace use:
std::merge();
and if you want to use your code use:
NSpace_IMUandGPS:ReadGPS();
You do not need to have things used in a particular namespace to be defined in that namespace.
Your namespace NSpace_IMUandGPS will be part of global nameless namespace. So, if structs which are used in function ReadGPS are not within any other namespace then you will find no problem accessing them inside the function ReadGPS.
You can call the function in main as follows:
NSpace_IMUandGPS::ReadGPS(/*all the required parameters*/);
In general, if variables/functions are not defined inside any namespace then they can be used by their name itself.
If variables/functions are defined inside some namespace then you need to specify the namespace when using them.
For example:
struct XYZ
{
int c;
};
namespace ABC
{
int a;
struct PQR
{
int b;
};
Func_1(XYZ st1, PQR st2);
}
Func_2(XYZ st1, ABC::PQR st2);
struct XYZ and Func_2 are part of global nameless namespace.
int a and struct PQR are part of namespace ABC.
Now if you see Func_1 can access struct XYZ even though its not defined inside namespace ABC. This is because namespace ABC is itself part of global nameless namespace.
But if a function which is present in global nameless namespace such as Func_2() then inorder to use things inside namespace ABC, you need to specify the name of namespace like ABC::PQR.
In C++, if I have
namespace myNamespace {
boost::whatever();
}
will the compiler look for whatever() in the boost namespace or in myNamespace::boost?
The question is not about whether it will look for boost::whatever, but where it will find boost itself.
If you have a nested namespace definition with the name boost, it will hide the global boost namespace at its point of declaration. The global boost namespace will be visible up until the point where myNamespace::boost is declared (§3.3.2/2).
[ Note: a name from an outer scope remains visible up to the point of declaration of the name that hides it. [ Example:
const int i = 2;
{ int i[i]; }
declares a block-scope array of two integers. — end example ] — end note ]
So if you're calling boost::whatever() before the nested name myNamespace::boost is created, it will look for the global boost namespace. You can qualify the name with ::boost if you always want it to find boost in the global namespace.
First of all I think you mean this:
namespace myNamespace {
using boost::whatever; // NOT boost::whatever();
}
Remember that C++ namespaces are mainly to avoid naming clashes not a design mechanism, which means when you are using a method of other namespaces in another one, you just call the original one and there is no copy in new namespace scope. So, when you call myNamespace::whatever(), compiler would choose boost::whatever() not myNamespace::boost::whatever() because there is no boost namespace declared inside myNamespace.
For more details on namespaces you could see:
http://en.cppreference.com/w/cpp/language/namespace
Assuming you want to call a function using some qualification, you may end up using a local namespace rather than a global namespace:
#include <iostream>
namespace A { void f() { std::cout << "::A::f()\n"; } }
namespace B {
namespace A { void f() { std::cout << "::B::A::f()\n"; } }
void g() { A::f(); }
void h() { ::A::f(); }
}
int main() {
B::g();
B::h();
}
If you want to make sure you are picking up a specific namespace you'll need to use absolute qualification as in ::A::f().
I'm learning C++ now. What are the complete legal entities that can be put in a namespace?
Legal entities here means valid members of a namespace
Oh, this is a real question. I'm coming from .net and I have the .net mindset.
Any code can be put inside namespace.
However main() function must be at global namespace. It cannot be put inside user-defined namespace.
namespace userns
{
int main()
{
return 0;
}
}
This program wouldn't compile link : http://www.ideone.com/k6SPc
Its because userns::main() will not be considered entry-point of the program; it became just like any other user function, not the standard main(). To compile it successfull, you've to add main() at global namespace:
namespace userns
{
int main()
{
return 0;
}
}
int main()
{
return 0;
}
This will compile link now : http://www.ideone.com/76Ynu
Anything can be put in a namespace (which is legal for C++, of course).
Actually, everything is in some namespace - the global namespace, if not specified.
Everything can be put in namespace except few "entities", which will not compile.
(1) Globally overloaded operator new and operator delete
namespace N
{
void* operator new (size_t size) // error
{ ... }
}
(2) Definition of the constructs which are declared in outer scope of the namespace; for example you have a class A declared globally then you cannot define its method inside your namespace N. In the same way, if you have method declared in a namespace N then you cannot put its definition inside namespace N::Nested (i.e. Nested is a namespace inside N).
//file
struct A {
void foo ();
static int i;
};
namespace N
{
int A::i = 0; // error
void A::foo() // error
{}
}
Demo: this is not allowed.
I remember at least these 2 restrictions from my experience. Don't know about specs.