Rampal Chaudhary
Rampal Chaudhary

Reputation: 707

Namespaces and scope visibility issue

I made a header file sampleheader.h with following code:

namespace sample_namespace
{
    int add(int n1,int n2)
    {
        return (n1 + n2);
    }
}

Now my main.cpp file is:

#include <iostream>
#include "sampleheader.h"
using namespace std;

int add(int n1, int n2)
{
  return (n1 + n2);
}

int main(void)
{
    using namespace sample_namespace;
    //cout<<add(5,7);
}

The project is built with no warning if i leave that line commented.It is understandable because the local add() function is defined in the global scope and add() function is made visible in the scope of main(). So no name conflict happens.

However, if I remove the comments, I get the following error:

"Ambiguous call to overloaded function"

First of all there should be no name conflict at all as explained by me above (if I'm right). But, if at all there is a name conflict why is it that it is notified by compiler only when I call the function. Such type of error should be shown as soon as a name conflicts (if at all).

Any help is appreciated.

Upvotes: 0

Views: 328

Answers (5)

Tom Kerr
Tom Kerr

Reputation: 10720

You cannot shadow symbols like that, only variable names (which is a warning on most compilers, i.e. a bad idea). using directives aren't precise in any sense, which I think is the assumption that most people make.

using directives will import a symbol into the scope. for instance, you can do things like this:

namespace foo {
  using namespace std;
}

foo::string val;

This sort of practice leads to some very annoying compiler errors to track down. Your simple example is clear where the error is. If you try doing it in a few hundred thousand lines of code, you will be much less pleased.

I would advise you not to acquire the habit of relying on the using directive. If you must, just do one type at a time.

using std::string;

Basically, this keeps you honest. And if there is a naming conflict, grep will take 30 seconds to uncover where the problem is.

If you just spend a couple weeks typing std:: in front of your types, you will get used to it. I promise that the amount of time you think you are saving is greatly exaggerated.

Upvotes: 0

MSalters
MSalters

Reputation: 179779

The reason why it's legal to declare both functions like that is because you can call both unambiguously, by qualifying them. That's why you get an error only when you make an unqualified call. Up to that point, there is not even a theoretical problem.

Intentionally, using namespace X; shouldn't introduce ambiguity errors by itself. That would very much defeat the purpose of namespaces. The common using namespace std; introduces many names that you'd reasonbly define yourself as well.

Upvotes: 0

Olympian
Olympian

Reputation: 768

I think this is because of compiler-optimisation. When your string is commented - he saw, that there are some function, but you don't use it, so he discard it. And when he saw that function useful - he want to insert function call, but can't chose which one you want.

Upvotes: -1

Joe
Joe

Reputation: 42577

"using namespace" does not hide other implementations. What it does in this case is make it ambiguous.

You have both sample_namespace::add and ::add with the same signature. Since you don't explicitly say which one to use, the compiler can't tell.

Declaring both functions is legal and unambiguous (which is why the compiler only complains when you use the function).

Upvotes: 1

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385098

Well, you explained it yourself.

When you have both int add() and int sample_namespace::add() in scope, the call is ambiguous. The statement add() could mean either of them.

There is no conflict in the functions co-existing because one is int add() and the other is int sample_namespace::add(). This is the entire purpose of namespaces.

You just have to be clear when you write code that uses them. If you get rid of your using namespace directives and always write explicit code, then you won't run into a problem:

#include <iostream>

namespace sample_namespace {
   int add(int n1, int n2) {
      return (n1 + n2);
   }
}

int add(int n1, int n2) {
   return (n1 + n2);
}

int main() {
    std::cout << sample_namespace::add(5,7);
}

(Also, defining non-inline functions in headers is A Bad Idea™.)

Upvotes: 2

Related Questions