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?
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).
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.
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.
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.
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With