Difference between sibling namespaces in nested vs global context - c++

I have some C++ libraries that are written using nested namespaces. These libraries use many mathematical functions that, for readability, are better off read without explicitly specifying namespaces. Right now, a simplified version of the code would look like this.
namespace Base::Sibling1 {
float cos(float x) { return cosf(x); }
};
namespace Base::Sibling2 {
using namespace Sibling1;
float f(float x) { return cos(x); }
};
We wanted to move to use flatter namespaces mostly to make it easier to extend the library with sibling code. We had hoped that a simple change like this would work:
namespace Sibling1 {
float cos(float x) { return cosf(x); }
};
namespace Sibling2 {
using namespace Sibling1;
float f(float x) { return cos(x); }
};
Instead this fails now since Sibling2::f() calls cos(x) that is now ambiguous.
I have two questions
why is it ambiguous now and not int the first version?
is it possible to obtain the behavior we had before without listing all functions explicitly using using Sibling1::cos?

The ambiguity is due to how using directives work.
[namespace.udir] (emphasis mine)
2 A using-directive specifies that the names in the nominated
namespace can be used in the scope in which the using-directive
appears after the using-directive. During unqualified name lookup
([basic.lookup.unqual]), the names appear as if they were declared in
the nearest enclosing namespace which contains both the
using-directive and the nominated namespace. [ Note: In this context,
“contains” means “contains directly or indirectly”. — end note ]
3 A using-directive does not add any members to the declarative
region in which it appears. [ Example:
namespace A {
int i;
namespace B {
namespace C {
int i;
}
using namespace A::B::C;
void f1() {
i = 5; // OK, C​::​i visible in B and hides A​::​i
}
}
namespace D {
using namespace B;
using namespace C;
void f2() {
i = 5; // ambiguous, B​::​C​::​i or A​::​i?
}
}
void f3() {
i = 5; // uses A​::​i
}
}
void f4() {
i = 5; // error: neither i is visible
}
— end example ]
So given your structure of namespaces, according to bit I made bold in paragraph 2, when you write
using namespace Sibling1;
It kinda translates to this
namespace /* Enclosing */ {
using Sibling1::cos;
namespace Sibling2 {
float f(float x) { return cos(x); }
};
}
The namespace I marked as enclosing is either Base or the global namespace. The "kinda" bit (according to paragraph 3) is that it's not an actual declaration being added. I.e. if something named cos already exists in /* Enclosing */, it's not a re-declaration. This is by design, because using directives can potentially bring a lot of names in, and so it shouldn't cause an error when the names they bring are not actually used.
In your case however, the name brought in is used.
When /* Enclosing */ is Base, it matches only one declaration, the one in Sibling1, as-if it was declared in Base.
When /* Enclosing */ is the global namespace, it matches the actual declaration there too, presumably the one brought in by math.h (you seem to be using that). So you get an ambiguity (the name refers to two potential entities).
So on the whole, compilers that reject this code are behaving as expected. While I understand your plight, I don't think there's really a problem for you to solve here. If client code finds Base::Sibling1::cos too verbose, it itself can employ a using directive of the form using namespace Base;. Or using a namespace alias to shorten things namespace sib1 = Base::Sibling1;.

The problem cannot be reproduced as you describe it. Moreover, there is no reason that the flattening alone introduces ambiguities, if you use expose in the siblings the same names you introduced in Base. So, the root cause is probably in some parts of the code you are not showing.
The second version does not define cosf(), so you probably are using some namespace. If in that namespae there is also a cos() you create an ambiguity between the two overloads. I could reproduce this by using namespace std:
#include <iostream>
#include <cmath>
using namespace std;
namespace Sibling1 {
float cos(float x) { return cosf(x); }
}
namespace Sibling2 {
using namespace Sibling1;
float f(float x) { return cos(x); }
}
Online demo: the compilation error indicates which are the candidates behind the ambiguity. If you now comment the using namespace out, the ambiguity goes away, and the code compiles. Online proof.
Namespaces are meant to avoid naming conflicts and keep control of ambiguities:
Creating a namespace and systematically using namespace everywhere defeats the whole purpose.
On the other side, long using lists are painful to maintain, especially if you have to repeat them in several sibling namespaces. This is probably why the Base and the nesting were created in the first place.
In the first version, you do not show what's in Base. It is possible that some more tailored using clauses are used therein instead of full namespaces: if selectively injecting the really required functions in the Base namespace, they are made available within the siblings avoiding ambiguity that can be introduced by injecting the name of unnecessary functions.

Related

Is it proper to use qualified lookup with no namespace on the left of the scoping operator (::name) in general code?

This sample code from cppreference.com:
#include <iostream>
int main() {
struct std{};
std::cout << "fail\n"; // Error: unqualified lookup for 'std' finds the struct
::std::cout << "ok\n"; // OK: ::std finds the namespace std
}
shows how ::name (no namespace on the left side of the scoping operator) refers to a name unambiguously.
An analogy can be made with filesystems. In filesystems, to refer to a file unambiguously, it is standard to refer to it by its absolute path, such as /home/username/hello.txt with a leftmost /.
On the other hand, it seems to be the established coding style in C++ to never refer to a name unambiguously, i.e., the scoping operator with a right argument only is rare. But since a fully unambigious lookup exists, it is surprising that ::std::cout isn't the standard coding style. It is always std::cout (no leftmost scoping operator, resulting in unqualified lookup of the leftmost namespace), which is error-prone, as the sample code shows.
Summary of the question: What serious reasons are there to support the style std::cout (unqualified lookup of the leftmost namespace) over ::std::cout (qualified lookup of everything)?
What serious reasons are there to support the style std::cout (unqualified lookup of the leftmost namespace) over ::std::cout (qualified lookup of everything)?
It's already hard enough to persuade people to write std::, let alone ::std::. The former is only "error-prone" if you have no naming standards. Much simpler is to forbid naming anything std.
std should be a reserved identifier, but for compatibility with C.
Argument-dependent lookup only works for unqualified function calls, which excludes using the nested-name-specifier ​:: if wanting to leverage ADL; [basic.lookup.argdep]/1
When the postfix-expression in a function call is an unqualified-id,
Using qualified names with a leading :: also forces developers to include possibly long-winded top-level->and->down namespace names in cases where these could otherwise be omitted, leading to verbosity that could give incentive for developers to create(/refactor) namespaces with (/into using) abbreviated names that are
more likely to collide with namespaces of other projects, and
more difficult to understand the meaning of for a future reader.
E.g., the following
namespace my_projects_well_named_top_level_namespace {
namespace my_core_utils {
void f() {};
}
namespace my_module_a {
void g() {
// Ok.
my_core_utils::f();
// Refactorer: This is too long.. let's rename the top-level.
::my_projects_well_named_top_level_namespace::my_core_utils::f();
}
} // namespace my_module_a
} // namespace my_projects_well_named_top_level_namespace
may, for the entirely wrong reasons (long and/or nested namespace names can be addressed locally within a TU using namespace aliases; see e.g. TotW #119), be re-factored into
namespace mp {
namespace my_core_utils {
void f() {};
}
namespace my_module_a {
void g() {
// Refactorer: Ok, nice!
::mp::my_core_utils::f();
}
} // namespace my_module_a
} // namespace mp
// Sometime later: Ehm, what is mp?
which, with its abbreviated name, may open up for collision (even silent ones) with 3rd party libraries which have happen to have chosen the same brilliantly abbreviated top-level namespace:
// ------------------- 3rdparty lib
namespace mp {
void f(int);
} // namespace mp
// ------------------- your project
namespace mp {
// We are now in the same declarative region
// as that of the 3rd party library.
struct S {
int x;
operator int() const { return x; }
};
namespace my_module_a {
void f(S) {}
} // namespace my_module_a
namespace my_module_b {
void g() {
// unqualified lookup _will not_ find my_module_a::f(S).
// ADL finds mp::foo(int) from the 3rd party lib
f(S{}); // #1
}
} // namespace my_module_b
} // namespace mp
(where of course the author of #1 has not followed the original refactorers intentional rule of using fully qualified names with leading nested-name-specifier).

C++11 inline namespace vs embedding the types directly in the enclosing namespace

Reading and researching a lot about the new C++11 feature - "inline namespace" I don't understand what the real benefit of this feature is.
I could easily have all the functions/types which are defined in an "inline namespace" placed directly in the enclosing one and have the same result.
So what is the real motivation of placing functions/types in an inline namespace?
Grouping the functions/types?
Is there any ADL related benefit in using "inline namespace"?
I thought ADL would behave the same was as there was an implicit "using" directive for this "inline namespace."
EDIT1:
So I think the following is the key advantage.
Let's say initially we have this:
namespace toplevel {
// Users can use toplevel::MyType
inline namespace current {
class MyType {};
} // inline namespace current
} // ns toplevel
Now, some new requirements, and we need a new version
to be available but keep the old one intact:
namespace toplevel {
// Users can use toplevel::MyType
// we can let the users know that we are going to deprecate it
// in favor of toplvel::next::MyType
inline namespace current {
class MyType {};
} // inline namespace current
// Users can use toplevel::next::MyType
namespace next {
class MyType {};
} // namespace next
} // ns toplevel
And finally do this. Move inline to the "next" namespace making
it the default. Still letting the users access to "current" but
with explicit ::current - i.e. this way: toplevel::current::MyType
BTW - my preference would even rename "current" to "deprecated".
namespace toplevel {
// Users can still use it by referring
// to toplevel::current::MyType
namespace current {
class MyType {};
} // inline namespace current
// Have this one the default one
// under toplevel
// Users can use the new one this way: toplevel::MyType
inline namespace next {
class MyType {};
} // namespace next
} // ns toplevel
Does it sound like a correct scenario?
The main motivation for C++ inline namespaces does indeed involve versioning. You are on the right track with your understanding, except for the final sentence in your question:
My preference would even rename "current" to "deprecated"
The whole idea of using inline namespaces is that the namespace names aren't changing -- rather, this feature allows for the namespace names to not need to change; existing names can live on forever without requiring much change to code.
Instead, at the time a version release is made (when what we used to think of as "current features" now become "deprecated features"), the namespace names can stay the same but their default status gets updated.
Let's see this in code:
namespace MyProject {
namespace Version1 {
void BoringStableFunction() {...}
}
inline namespace Version2 {
void BoringStableFunction() {...}
void LatestAndGreatest(int x) {...}
}
}
The clients of this software probably will most often be using it by simply calling MyProject::BoringStableFunction() and maybe MyProject::LatestAndGreatest(11), perhaps without even knowing that two separate versions of MyProject exist. And that convenience can be a good thing. If a client does know that there were two different versions, and intentionally wants to use the old one (before LatestAndGreatest() had been invented), he can still do so by calling MyProject::Version1::BoringStableFunction().
Note that a client is allowed to write his code as MyProject::Version2::BoringStableFunction(). Doing so is the client essentially saying "I want to call that current #2 version, and I want that implementation which I'm using to stay the same -- even if that MyProject project gets updated later on"
Notice how I can perform additional development without affecting any of my existing clients:
namespace MyProject {
namespace Version1 {
void BoringStableFunction() {...}
}
inline namespace Version2 {
void BoringStableFunction() {...}
void LatestAndGreatest(int x) {...}
}
namespace Version3 {
void BoringStableFunction() {...}
void LatestAndGreatest(std::string x) {...}
}
}
When I'm ready to release my changes to the general public, only this tiny edit needs to be made:
namespace MyProject {
namespace Version1 {
void BoringStableFunction() {...}
}
namespace Version2 {
void BoringStableFunction() {...}
void LatestAndGreatest(int x) {...}
}
inline namespace Version3 {
void BoringStableFunction() {...}
void LatestAndGreatest(std::string x) {...}
}
}
Most of the clients had been calling MyProject::BoringStableFunction(). Their code won't need to be edited; it is still syntactically valid. But they will now suddenly be taking advantage of any new implementation that I might have changed within BoringStableFunction().
If they had been so bold as to be using my MyProject::LatestAndGreatest(11), they will need to be informed that they now need to update their usage. So this demonstrates that, even with inline namespaces, thought still needs to be put into the contract between a programmer and his client.

Namespace qualified names INSIDE a user namespace

In C++, if I have
namespace myNamespace {
boost::whatever();
}
will the compiler look for whatever() in the boost namespace or in myNamespace::boost?
The question is not about whether it will look for boost::whatever, but where it will find boost itself.
If you have a nested namespace definition with the name boost, it will hide the global boost namespace at its point of declaration. The global boost namespace will be visible up until the point where myNamespace::boost is declared (§3.3.2/2).
[ Note: a name from an outer scope remains visible up to the point of declaration of the name that hides it. [ Example:
const int i = 2;
{ int i[i]; }
declares a block-scope array of two integers. — end example ] — end note ]
So if you're calling boost::whatever() before the nested name myNamespace::boost is created, it will look for the global boost namespace. You can qualify the name with ::boost if you always want it to find boost in the global namespace.
First of all I think you mean this:
namespace myNamespace {
using boost::whatever; // NOT boost::whatever();
}
Remember that C++ namespaces are mainly to avoid naming clashes not a design mechanism, which means when you are using a method of other namespaces in another one, you just call the original one and there is no copy in new namespace scope. So, when you call myNamespace::whatever(), compiler would choose boost::whatever() not myNamespace::boost::whatever() because there is no boost namespace declared inside myNamespace.
For more details on namespaces you could see:
http://en.cppreference.com/w/cpp/language/namespace
Assuming you want to call a function using some qualification, you may end up using a local namespace rather than a global namespace:
#include <iostream>
namespace A { void f() { std::cout << "::A::f()\n"; } }
namespace B {
namespace A { void f() { std::cout << "::B::A::f()\n"; } }
void g() { A::f(); }
void h() { ::A::f(); }
}
int main() {
B::g();
B::h();
}
If you want to make sure you are picking up a specific namespace you'll need to use absolute qualification as in ::A::f().

namespace search in c++

I found a problem concerning namespace search.
The following simplified code failed to compile:
namespace A {
namespace B {
class Test {
};
}
namespace C {
namespace B {
typedef B::Test AnAlias;
}
}
}
The compiler complains that Test in namespace A::C::B does not name a type.
The problem seems to be that the compiler sees a namespace B inside namespace C and does not no further search. I would have exspected that he also would look in namespace A (which is a enclosing namespace) and find the B::Test there.
If I rename C::B everything is fine.
If I qualify A::B::Test everything is fine.
If I put the typedef directly in namespace A::C everything is fine.
This behavior was tested with gcc 4.1 and intel 12 compiler. (both for linux).
Are the compilers right?
The B in typdef B::Test resolves to A::C::B. If you're going to reuse the name B, you need to specify it to remove the ambiguity. The compilers are behaving properly. IIRC, names are resolved to the closest declaration to its use or reference. In this case A::C::B is the closest declaration to the typedef.

Creating a C++ namespace in header and source (cpp)

Is there any difference between wrapping both header and cpp file contents in a namespace or wrapping just the header contents and then doing using namespace in the cpp file?
By difference I mean any sort performance penalty or slightly different semantics that can cause problems or anything I need to be aware of.
Example:
// header
namespace X
{
class Foo
{
public:
void TheFunc();
};
}
// cpp
namespace X
{
void Foo::TheFunc()
{
return;
}
}
VS
// header
namespace X
{
class Foo
{
public:
void TheFunc();
};
}
// cpp
using namespace X;
{
void Foo::TheFunc()
{
return;
}
}
If there is no difference what is the preferred form and why?
The difference in "namespace X" to "using namespace X" is in the first one any new declarations will be under the name space while in the second one it won't.
In your example there are no new declaration - so no difference hence no preferred way.
Namespace is just a way to mangle function signature so that they will not conflict. Some prefer the first way and other prefer the second version. Both versions do not have any effect on compile time performance. Note that namespaces are just a compile time entity.
The only problem that arises with using namespace is when we have same nested namespace names (i.e) X::X::Foo. Doing that creates more confusion with or without using keyword.
There's no performance penalties, since the resulting could would be the same, but putting your Foo into namespace implicitly introduces ambiguity in case you have Foos in different namespaces. You can get your code fubar, indeed. I'd recommend avoiding using using for this purpose.
And you have a stray { after using namespace ;-)
If you're attempting to use variables from one to the other, then I'd recommend externalizing them, then initializing them in the source file like so:
// [.hh]
namespace example
{
extern int a, b, c;
}
// [.cc]
// Include your header, then init the vars:
namespace example
{
int a, b, c;
}
// Then in the function below, you can init them as what you want:
void reference
{
example::a = 0;
}
If the second one compiles as well, there should be no differences. Namespaces are processed in compile-time and should not affect the runtime actions.
But for design issues, second is horrible. Even if it compiles (not sure), it makes no sense at all.
The Foo::TheFunc() is not in the correct namespacein the VS-case. Use 'void X::Foo::TheFunc() {}' to implement the function in the correct namespace (X).
In case if you do wrap only the .h content you have to write using namespace ... in cpp file otherwise you every time working on the valid namespace. Normally you wrap both .cpp and .h files otherwise you are in risk to use objects from another namespace which may generate a lot of problems.
I think right thing to do here is to use namespace for scoping.
namespace catagory
{
enum status
{
none,
active,
paused
}
};
void func()
{
catagory::status status;
status = category::active;
}
Or you can do the following:
// asdf.h
namespace X
{
class Foo
{
public:
void TheFunc();
};
}
Then
// asdf.cpp
#include "asdf.h"
void X::Foo::TheFunc()
{
return;
}