Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I explicitly refer to an enclosing namespace when an inline namespace exists?

Tags:

Please consider this code:

#include <iostream>  namespace Foo{      void ool()  // Version A     {         std::cout << "Foo::ool" << std::endl;     }      inline namespace Bar{         void ool() // Version B         {             std::cout << "Foo::Bar::ool" << std::endl;         }     } }   int main() {     Foo::ool();  // <- error } 

Both Clang and G++ correctly mark Foo::ool as ambiguous. I can call Foo::Bar::ool without problem but is there a way to call the version A without changing its declaration?

I found people in similar position trying to understand what happens but I did not see a solution for this case.

I am in this situation because I have a project that includes a declaration of std::__1::pair and std::pair, made in different places, with std::__1 being an inline namespace. I need the code to point to the std::pair explicitly. Is there a solution for that?

like image 735
YvesQuemener Avatar asked Aug 25 '15 08:08

YvesQuemener


People also ask

What is inline namespace?

Inline namespaces are a library versioning feature akin to symbol versioning, but implemented purely at the C++11 level (ie. cross-platform) instead of being a feature of a specific binary executable format (ie. platform-specific).

How do you call a namespace function in C++?

Namespaces in C++ You only need to prefix the function you wish to call with namespace_name:: -- similar to how you would call a static member function of a class. Another convenience of namespaces is that they allow you to use the same function name, when it makes sense to do so, to perform multiple different actions.

Can you use two namespaces C++?

You can have the same name defined in two different namespaces, but if that is true, then you can only use one of those namespaces at a time. However, this does not mean you cannot use the two namespace in the same program. You can use them each at different times in the same program.

What does namespace std mean in C++?

Explanation: It is known that “std” (abbreviation for the standard) is a namespace whose members are used in the program. So the members of the “std” namespace are cout, cin, endl, etc. This namespace is present in the iostream. h header file.


2 Answers

I don't think that is possible; from cppreference:

Qualified name lookup that examines the enclosing namespace will include the names from the inline namespaces even if the same name is present in the enclosing namespace.

However, it seems you are not actually in the situation you describe, as you say that the two definitions are pulled from different files. Thus you "bookmark" the more external definition in order to be able to call it when you need it:

#include <iostream>  // Equivalent of first include namespace Foo{     void ool()  // Version A     {         std::cout << "Foo::ool" << std::endl;     } }  const auto& foo_ool = Foo::ool;  // Equivalent of second include namespace Foo{     inline namespace Bar{         void ool() // Version B         {             std::cout << "Foo::Bar::ool" << std::endl;         }     } }  int main() {     foo_ool(); // Works } 

If the thing you want to bookmark is a type, a simple using directive should suffice. The equivalent code for you would look like:

#include <my_first_include>  // bookmark code  #include <my_second_include>  // rest of the code 
like image 176
Svalorzen Avatar answered Oct 20 '22 01:10

Svalorzen


You cannot unambiguously refer to the symbol defined in the enclosing namespace once the inline namespace has been seen.

In particular for you case, the qualified lookup in main is rightfully flagged as being ambiguous (as you said yourself). See the last point on cppreference:

Qualified name lookup that examines the enclosing namespace will include the names from the inline namespaces even if the same name is present in the enclosing namespace.


Yet, has other pointed out in comments, you are probably facing a problem of configuration in your toolchain invocation when you try to use std::pair.

To fix you problem, you need to make sure the compiler is invoked to compile C++11 code, which would be with the flag:

-std=c++11 or -std=c++0x depending on your version of Clang/GCC

To give further context:
The inline namespace is a C++11 feature, mainly introduced to allow for symbol versioning in libraries. A C++ standard library implementation could then define different versions of symbols in nested namespaces (with non-standard names), and depending on the requested library version when compiling, the toolchain defines one of those nested namespaces as inline. It seems you are using a c++11 version of the library (since it defines some symbols, in particular pair, in the inline namespace _1), so having symbols in an inline namespace in actually what you want.

like image 32
Ad N Avatar answered Oct 19 '22 23:10

Ad N