// main.cpp
const double MAX = 3.5;
namespace ns
{
const int MAX = 3;
}
int main()
{
}
will this cause redefinition error?
I'm referring to this MSDN page, which says in the Remarks section that this is an error.
Update: I think I may miss one important statement when copying around the code.
using ns::MAX;
No - I don't see how that code would cause a redefinition error.
And in fact, you can compile it and see for yourself.
EDIT: Following up now that you've supplied the link to the MSDN page you mentioned...
That MSDN page is talking about name clashes in the context of a using directive:
If a local variable has the same name as a namespace variable, the
namespace variable is hidden. It is an error to have a namespace
variable with the same name as a global variable.
Here's an example of a local variable hiding a namespace variable that's been brought into scope by a using directive:
namespace ns
{
const int MAX = 3;
}
using namespace ns;
int main()
{
int MAX = 4; // local
int test = MAX; // test is 4, because the local variable is used
// as the namespace variable is hidden
}
The inclusion of the using directive brings all of the names declared within the ns namespace into scope. However, when I assign the value of MAX to test, it's the local variable MAX that is used in the assignment because the namespace variable MAX is hidden. The local variable takes precedence and hides the namespace variable.
Now here's an example of a clash between a namespace variable and a global variable.
Consider this amended piece of code (and you can see it compile here):
const double MAX = 3.5;
namespace ns
{
const int MAX = 3;
}
using namespace ns;
int main()
{
int test = MAX;
}
Again, the using directive brings ns:MAX into scope, and the global variable MAX is also in scope.
When I go to use the variable called MAX in main(), the compiler reports an error because the name MAX is now ambiguous: it has no way of knowing which MAX we are referring to, as there are two non-local MAXs to choose from: neither has any precedence.
prog.cpp: In function ‘int main()’:
prog.cpp:13: error: reference to ‘MAX’ is ambiguous
prog.cpp:2: error: candidates are: const double MAX
prog.cpp:6: error: const int ns::MAX
prog.cpp:13: error: reference to ‘MAX’ is ambiguous
prog.cpp:2: error: candidates are: const double MAX
prog.cpp:6: error: const int ns::MAX
They wouldn't because one is in file scope and the other in namespace scope.
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;
}
In a big project, I have a .h file which defines a lot of constants within a namespace. Introducing const char* constants results in linker errors complaining of multiple definitions.
ex.h
#include <string>
namespace Dv
{
const int MAX = 10;
const std::string NAME = "bobo";
const char* NAME2 = "fred"; // <-- ERROR: multiple definition of `Dv::NAME2'
}
exA.cpp
#include "ex.h"
void aFunction() { printf("this is aFunction\n"); }
exB.cpp
#include "ex.h"
void aFunction(void);
int main(int argc, char **argv)
{
aFunction();
return 0;
}
Compile and Link
g++ -c exA.cpp
g++ -c exB.cpp
g++ exA.o exB.o -o ex
exB.o:(.data+0x0): multiple definition of `Dv::NAME2'
exA.o:(.data+0x0): first defined here
collect2: ld returned 1 exit status
The linker error happens if NAME2 is included in the .h file. Why?
If MAX is also a POD (like char[]?), why does the linker not complain of multiple int MAX definitions? (or multiple std::string NAME definitions for that matter?)
I don't understand what's special about char[] in this situation.
Thanks
According to the C++ Standard (3.5 Program and linkage)
3 A name having namespace scope (3.3.6) has internal linkage if it is
the name of
— a non-volatile variable that is explicitly declared const or constexpr and neither explicitly declared extern nor previously
declared to have external linkage; or
and
4 An unnamed namespace or a namespace declared directly or indirectly
within an unnamed namespace has internal linkage. All other
namespaces have external linkage. A name having namespace scope that
has not been given internal linkage above has the same linkage as the
enclosing namespace if it is the name of — a variable; or
In this namespace definition
namespace Dv
{
const int MAX = 10;
const std::string NAME = "bobo";
const char* NAME2 = "fred"; // <-- ERROR: multiple definition of `Dv::NAME2'
}
(the only) variable NAME2 is not a constant and hence has external linkage.
You could make it as having internal linkage defining it for example with keyword static. For example
namespace Dv
{
const int MAX = 10;
const std::string NAME = "bobo";
static const char* NAME2 = "fred";
}
Or could define it as a constant
namespace Dv
{
const int MAX = 10;
const std::string NAME = "bobo";
const char * const NAME2 = "fred";
}
I'm trying to get a reference to my class but it seems to is not declared.
This means it's undeclared:
#include <iostream>
using namespace std;
class time
{
private:
int sec;
int mins;
int hours;
public:
void setSeconds(int x)
{
sec = x;
}
int getSeconds()
{
return sec;
}
};
int main()
{
time to;
to.setSeconds(10000000);
cout << to.getSeconds() << endl;
return 0;
}
The error reads:
main.cpp: In function 'int main()':
main.cpp:29:10: error: expected ';' before 'to'
time to;
^
main.cpp:29:12: warning: statement is a reference, not call, to function 'time' [-Waddress]
time to;
^
main.cpp:29:12: warning: statement has no effect [-Wunused-value]
main.cpp:30:5: error: 'to' was not declared in this scope
to.setSeconds(10000000);
^
std::time is a function in the C++ standard library and, since you're using namespace std, that's being used by default instead of your class.
You can't even write ::time to reference yours, because your compiler's standard library implementation happens to include the old C ::time as well before wrapping it into namespace std.
Use some or all of these suggestions:
give your class a better, more unique name
write class time to reference your class (this ensures the type time is used, but is a poor hack)
use a namespace yourself to avoid all future ambiguities (this is recommended)
You should also stop using namespace std in general to help avoid as much trouble as possible, though it cannot directly aid you in this case.
Clang give a better error message:
time.cpp:29:5: error: must use 'class' tag to refer to type 'time' in this scope
time t;
^
class
/usr/include/time.h:192:15: note: class 'time' is hidden by a non-type declaration of 'time' here
extern time_t time (time_t *__timer) __THROW;
^
It isn't related to using namespace std. Rather the global time function is conflicting.
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
}
I have such pretty little code:
//example1
namespace
{
int a;
}
int a;
main()
{
a++;
return 0;
}
Of course, g++ 4.6.1 compiler can't compile it and outputs an error:
./temp.cpp: In function ‘int main()’:
./temp.cpp:10:5: error: reference to ‘a’ is ambiguous
./temp.cpp:6:5: error: candidates are: int a
./temp.cpp:2:9: error: int {anonymous}::a
It's all right!
But when I delete the reference to variable "a" within "main" function, the program is being compiled well:
//example2
namespace
{
int a;
}
int a;
main()
{
return 0;
}
1) Why does the g++ compiler allows the definition of variable "a", when in such case it disallows the references to it?
2) Is it just the g++ compiler's feature, and no other compiler is able to compile such code (example2)?
3) Does the g++ compiler have corresponding flags to interpret such code (example2) as faulty?
Thanks a lot for everyone!
The second example is valid because you can still access the global a from outside that translation unit.
The a in the anonymous namespace provides a definition for a variable that has internal linkage. The a at global namespace scope is a definition for a variable with external linkage. You can declare a extern int a; in a different translation unit and use it.
Just because you can't reference the a in the anonymous namespace from main doesn't mean the code is invalid.
The a in the anonymous namespace can still be referenced from within the anonymous namespace.
The global a can be referenced from everywhere (you'd have to use ::a in main to remove the ambiguity).
The short answer is "because there's nothing illegal about it". It's just using a in main that is wrong. If you use ::a it will give you the global one (without the namespace).
And you can use a inside the namespace itself, e.g. we could have a function:
namespace {
int a;
int work_with_a()
{
a += 2;
return a;
}
}
int a;
int main()
{
::a++;
int b = work_with_a();
cout << ::a + b;
}