Namespace Search Order

I have two namespaces, each of which has a function with the same name. If from one of the namespaces I want to call a function that matches the best. From a function in NamespaceA, if I call MyFunction (...), of course, it uses the one in NamespaceA. However, if I add "using NamespaceB :: MyFunction", I would expect the described behavior. However, in fact, I see that it ALWAYS finds the NamespaceB function, although I'm in NamespaceA. HOWEVER, if I ALSO add the use of :: NamespaceA (although I'm already in NamespaceA), it works as I expected. Below is a demo. Can anyone explain how this works?

#include <iostream> namespace NamespaceA { void DoSomething(); void MyFunction(int object); } namespace NamespaceB { void MyFunction(float object); } namespace NamespaceA { void DoSomething() { using NamespaceA::MyFunction; // Note that without this line the lookup always fins the NamespaceB::MyFunction! using NamespaceB::MyFunction; MyFunction(1); MyFunction(2.0f); } void MyFunction(int object) { std::cout << "int: " << object << std::endl; } } namespace NamespaceB { void MyFunction(float object) { std::cout << "float: " << object << std::endl; } } int main(int argc, char *argv[]) { NamespaceA::DoSomething(); return 0; } 
+7
source share
3 answers

This refers to the order in which various parts of the program are scanned to find a name. For the situation you are talking about, this is related to the search volume of the top-level block of the function in front of the surrounding namespace. Basically, a using declaration brings this name to the top-level domain of DoSomething , and since this region is visible in front of the enclosing region of the namespace, then if a corresponding function is found there, then the space region of the enclosing space isn’t considered.

I masked a lot of things that are not relevant to your example (for example, if the argument was not a built-in type, believe it or not, the names from the area in which this type was defined, also see section 3.4 here . It's pretty scary, about 13 pages to describe all this, but don’t worry if you’re really not interested, because most of the material exists, so that it “works as you expect”, more or less. This document is not a standard, but actually working draft with some corrections and so this is basically a real C ++ Standard, plus some fixes.

+2
source

i believe that namespaces use the same rules as variables. therefore, if you have a local namespace, the search will occur there before moving on to the outside.

I’m not sure what the rules are for the situation when you import two namespaces with the same function names, but you should always fully qualify function calls in this scenario just for clarity, instead of relying on some nuance the language implementation for namespaces, with that people don’t know.

0
source

The short answer . The local specific name, and the name declared using the using declaration, hides non-local names.

Detailed response:

Your question is very interesting. I did not open the C ++ 98.03.11 standards for this question, but open the Bjarne Stroustrup book

A namespace is a named area. Ambiguity can be eliminated using two methods:

  • create synonyms with NS :: x; (Using declaration)
  • Create synonyms for all variables using NS :: x namespace (Using the directive)

The answer to your question is here:

 Appendix B 10.1 local definitions, and names defined with using-declaration hides the name of a non-local definitions. 

Bonus with the opposite situation:

Also if you

 using NamespaceA::MyFunction; using NamespaceB::MyFunction; 

change to

 using namespace NamespaceB; 

Then, due to the text below, you get a situation with calling only void MyFunction (int object)

 8.2.8.2 Names explicitly declared in namespace (also made with using declaration) have priority over the names made available by using directives 

Additional code for the game:

 #include <iostream> // var in global namespace const char* one = "G_one"; // vars in named namespace namespace NS1 { const char* one = "NS1_one"; const char* two = "NS1_two"; const char* three = "NS1_three"; } namespace NS2 { const char* one = "NS2_one"; const char* two = "NS2_two"; const char* three = "NS2_three"; } int main(int argc, char *argv[]) { using namespace NS1; // using-directive using namespace NS2; // using-directive // const char* two = "L_two"; // local namespace using NS2::two; // using-declaration // C++ rules // Local names and names with using-declarations // takes precedence over the name of the NS std::cout << "two: " << two << std::endl; //std::cout << "three: " << three << std::endl; // ambiguous symbol // But the name in global-namespace does not have priority over imported name from namespace //std::cout << "one: " << one << std::endl; // ambiguous symbol. Because wGlobal names does not have priority over return 0; } 
0
source

All Articles