It looks to me like a problem with your particular compiler. It doesn't give an error with the compilers I have handy.
Use a namespace
namespace myNamespace
{
class random
{
public:
random(){ std::cout << "yay!! i am called \n" ;}
};
}
myNamespace::random r1;
If you have name collision problems use a namespace:
namespace mydata{
class random{things};
}
And then call it mydata::random;
You're running into the POSIX random()
function.
How do you avoid collisions? Know your libraries. Or you can do as I did to diagnose this, say man random
. There it was, random(3).
I don't know what your namespace problem is, but it sounds like a separate question.
In the case of g++, use command line option -ansi
. This removes the non-standard function random
from stdlib.h.
By default, g++ compiles as -std=gnu++98
, which is "The 1998 ISO C++ standard plus amendments plus GNU extensions". So your code has done nothing wrong in order to be portable. It's just that without -ansi
, you aren't using a compliant compiler.
These BSD (and Posix) stdlib functions are among those GNU extensions. From the glibc documentation:
http://www.gnu.org/s/libc/manual/html%5Fnode/BSD-Random.html
"There is no advantage to using these functions with the GNU C library; we support them for BSD compatibility only."
In general, if you want to write code that's portable to non-compliant compilers, then you just have to memorise the peculiarities of every single compiler in the world. GCC and MSVC are good ones to start with. Even with -ansi
, you can make gcc non-compliant with other command-line options, such as -O2. This happened with the -fdelete-null-pointer-checks
fiasco that hit the linux kernel a while back). Same goes for platforms whose libraries "extend" C (and hence C++), like BSD and Posix.
The reason there's a C standard in the first place is supposed to be so that you don't have to worry about this stuff, and personally I think it's unfortunate that other standards mess with C standard headers. But I'd guess that the fact of those functions being in stdlib on BSD dates from before C89. If so, then presumably it avoided a breaking change on BSD and other unixes at the time.
Btw, I found out that random()
was in stdlib.h with g++ -E
, which is useful when you want to know what on earth the system headers are doing to your program. I assumed that searching the web for "random" would be pointless. But "stdlib random" worked quite well.
Are you including cstdlib? I get the error you show when I include it, I don't if I don't.
the g++ compiler which i m using correctly compiled and ran your program. I m using MinGw 5.1.6 for running g++ on windows..
In general you avoid ambiguity errors by resolving them explicitly. Without putting your duplicate symbol in another namespace this can't work (except for cases where elaborated type specifiers help as litb points out) as you have two symbols in the same namespace and can't refer to either of them explicitly.
When putting your symbol in a namespace, you can:
- fully qualify the name:
myNamespace::mySymbol(x);
- explicitly resolve the ambiguity:
using myNamespace::mySymbol;
Note that pulling all symbols from your namespace in via using myNamespace;
doesn't help as this doesn't resolve the ambiguity.
For full qualification its common to use short-hand names:
namespace mns = myNamespace;
mns::mySymbol(x);
Why does your using namespace...
not work, while your using ...
works? First i want to show you another way to solve it by use of an elaborated type specifier:
int main() {
// ...
static class random r2; // notice "class" here
// ...
}
That works because "class some_class" is an elaborated type specifier, which will ignore any non-type declarations when looking up the name you specify, so the POSIX function at global scope, which has the same name, will not hide the class name. You tried two other ways to solve it: Using directives and using declarations:
Then, you tried to stick the type into a namespace, and tried
using namespace foo;
in main - why did it not work?namespace foo { class random { public: random(){ std::cout << "yay!! i am called \n" ;} }; } int main() { using namespace foo; static random r2; // ambiguity! return 0 ; }
You might wonder why that is so, because you might have thought that the using directive declares the names of
foo
into the local scope of main - but that's not the case. It's not declaring any name, actually it's just a link to another namespace. It's making a name visible during unqualified name lookup in that case - but the name is made visible as a member of the namespace enclosing both the using-directive and the denoted namespace (foo
). That enclosing namespace is the global namespace here.So what happens is that name lookup will find two declarations of that name - the global POSIX
random
declaration, and the class declaration withinfoo
. The declarations were not made in the same scope (declarative region), and so the function name doesn't hide the class name as usual (seeman stat
for an example where it does), but the result is an ambiguity.A using declaration however declares one name as a member of the declarative region that it appears in. So, when
random
is looked up starting frommain
, it will first find a name that refers to the declaration ofrandom
infoo
, and this will effectively hide the global POSIX function. So the following worksnamespace foo { class random { public: random(){ std::cout << "yay!! i am called \n" ;} }; } int main() { using foo::random; static random r2; // works! return 0 ; }