We usually use namespaces to avoid name clashes in C++. But what if there are two different libraries which have a class, that has the same namespace name and class name? Is there a work around?
(PS: I am pretty sure, that its a rare scenario, I never faced it, just happened to cross my mind)
The idea is to use something related to the company/group itself.
This way the collision is avoided.
It is highly unlikely that a profesional library would choose something trivial like MyNamespace.
It would be like Company::Project::Module.
This is even clearer in java where you have org.apache etc
It might happen, but its not very likely to do you much damage. Not only do the namespace names have to be exactly the same, you have to actually use both libraries. Chances are, if they've named their namespaces in some reasonable way, their names will indicate their purpose -- even if there are two libraries that use GenericXMLParser as their namespace, and probably have some class names in common, do you really expect to be using them both on one project?
This does make certain namespace names a bad idea, such as boost or Ogre. Anyone using those (except the original users) should expect their library to be unusable in many cases. A less common name, like Pie, is probably going to be fine for by far most people in by far most cases. If both libraries using Pie become widely used, one might have to change; in that case, the namespace renaming trick can be used to keep backwards compatibility with old code.
You can rename one of the namespace with
namespace <new> = <old>;
But that will only get you so far. Here is an example :
namespace aaa {
int foo() { return 42; }
}
namespace zzz {
int foo() { return -42; }
}
namespace bbb = aaa;
int main() {
aaa::foo(); //Original namespace is still there
bbb::foo(); //but it is also available with a new name
zzz::foo(); //No clash, that's what namespaces are for
return 0;
}
But since the rename is really just an alias, the aaa namespace stays. This code will get you a duplicate symbol error (no matter how deep it is buried in .h files) :
namespace aaa {
int foo() { return 42; }
}
namespace aaa {
int foo() { return -42; }
}
You can get around it somehow by wrapping the clashing namespace in your own namespace declaration, like this :
#include <stdio.h>
namespace aaa {
int foo() { return 42; }
}
namespace zzz {
#include "clash.h"
}
namespace aaa2 = zzz::aaa;
int main() {
printf("%d\n", aaa::foo()); //Original works
printf("%d\n", aaa2::foo()); //Non-clashing through alias
printf("%d\n", zzz::aaa::foo()); //Non-clashing real name
return 0;
}
But that solution too will work only in trivial code, because all the included files in clash.h will end up in the zzz namespace.
+I think renaming std is forbidden though, if only by common sense.
Related
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.
I am familiar with the following use of namespaces.
In the header file (for example people.h) I describe interface of a name space. For example:
namespace people{
int getAge(str Name);
void setName(str Name);
}
Then in people.cpp I define the methods from the space name:
#include "people.h"
int people::getAge(str Name) {
something_1;
something_2;
}
void people::setName(str Name) {
something_1;
}
However, in a header file that I have I see that in addition to the namespace people there are also interfaces of other namespaces (for example namespace dogs). And these name spaces are not defined in the people.cpp file.
So, I assumed that (because of some strange reason) the interface for the namespace dogs is put into the people.h and then then the name space dog is defined in the "dogs.cpp" file. So, in other words I assumed that two different name spaces are defined in two different cpp files but their interface is described in one header file. However, this assumption seems to be wrong because I found that there are many header files that declare "namespace dogs".
So, I assume that namespace dogs in the 2people.h" file has another function but I cannot figure out what function it is. Could anybody please help me with that?
ADDED
The code that I try to understand is written not by me and it works fine. So, it should make sense. May be I was not clear enough. So, I try to give an example:
In the header file (people.h) I have:
namespace etet
{
class date;
}
namespace xsystem{
class estimation_module;
}
namespace people {
a_lot_of_different_stuff;
}
Then the people.cpp defines all the methods that belong to the people name space.
The "namespace interface" is a misleading concept. A namespace is just a bounch of names grouped together under a surname (like you and your brothers and sisters). It has no "interface" because there is no namespace "obejct".
The
#include "people.h"
int people::getAge(str Name) {
something_1;
something_2;
}
void people::setName(str Name) {
something_1;
}
is perfectly equivalent to
#include "people.h"
namespace people
{
int getAge(str Name) {
something_1;
something_2;
}
void setName(str Name) {
something_1;
}
}
may be this is more familiar, or may be not.
The fact an header declares functions not present in a cpp, just means they are probably present in another one.
About the fact that the namespace name { ..... } declaration can be repeated in many files, each containing various function is perfectly normal, since the namespace keyword does not declare an object. It just group names. And -in fact- sayning a namespace is "declared" is a common language abuse. What is declared is the name of the namespace.
And different names declare in different places can belong to a same group. there is nothing mysterious in that.
You lexicon makes me thinking you are confusing namespaces with classes and structs
ADDED:
After your clarification, it looks like the a_lot_of_different_stuff contains declarations that use etet::date and xsystem::estimation_module;
This names (and only the names) must be known to the compiler, but the header cannot recursively include ther respective headers because they most likely already included people.h.
A typical "curculare reference" problem, like in here, but involving different namespaces.
You're confusing namespaces and classes. Typically, a class definition occurs in a header file (.h) and the implementation of its member functions appear in the corresponding implementation file (.cpp).
A namespace works differently to a class. If a class is defined in multiple translation units, it must have precisely the same tokens in all of them. You can't even reorder members, even if it would result in the exact same class. It's easy to meet this requirement by using the above described header files. Each translation unit that needs a class foo contains the contents of foo.h because they do #include "foo.h" when they need it. Of course they all contain precisely the same definition of foo bceause they all included foo.h.
However, this is very different to namespaces. A namespace can be introduced multiple times across the same and different translation units without it being the same tokens every time. Something like this is totally fine:
namespace bar {
void baz();
struct x;
}
// some stuff
namespace bar {
void do_something(x);
}
Each occurence of namespace bar introduces some declarations to that namespace.
You will often have many classes defined in the same namespace. Each header for those classes will do namespace whatever { ... } and introduce the class definition into that namespace.
Sometimes you will even want to introduce things to multiple namespaces or nested namespaces in a single header file. There's nothing to stop you doing that. A possible situation for doing that is if you want to forward declare something from another namespace. Let's say you have a class defined in people.h like so:
namespace people {
class person {
dogs::dog* pet_dog;
};
}
Now, this class needs to know about the type dog in the dogs namespace. One way to do his would be to #include "dogs.h". However, since pet_dog is only a pointer, we can do with an incomplete type, so we can forward declare dog like so:
namespace dogs {
class dog;
}
namespace people {
class person {
dogs::dog* pet_dog;
};
}
Let's say the Acme company releases a useful library with an extremely ugly C API. I'd like to wrap the structs and related functions in C++ classes. It seems like I can't use the same names for the wrapper classes, because the original library is not inside a namespace.
Something like this is not possible, right?
namespace AcmesUglyStuff {
#include <acme_stuff.h> // declares a struct Thing
}
class Thing {
public:
...
private:
AcmesUglyStuff::Thing thing;
};
Linking will be a problem.
The only way I can think to wrap the library, and not pollute my namespace with the C library names, is a hack like this, reserving space in the class:
// In mything.h
namespace wrapper {
class Thing {
public:
...
private:
char impl[SIZE_OF_THING_IN_C_LIB];
};
}
// In thing.cc
#include <acme_stuff.h>
wrapper::Thing::Thing() {
c_lib_function((::Thing*)impl); // Thing here referring to the one in the C lib
}
Is that the only way? I'd like to avoid putting prefixes on all my class names, like XYThing, etc.
Seems like you're making this harder than it needs to be.
#include "acme_stuff.h" // puts all of its names in global namespace
namespace acme {
class Thing {
public:
// whatever
private:
::Thing thing;
};
}
Now just use acme::Thing rather than Thing.
If it's really important to you to not have the C names in the global namespace, then you need a level of indirection:
namespace acme {
class Thing {
public:
Thing();
~Thing();
// whatever
private:
void *acme_thing;
};
}
In your implementation file, #include "acme_stuff.h", in your constructor create a new ::Thing object and store its address in acme_thing, in your destructor delete it, and in your member functions cast acme_thing to type ::Thing*.
It's not a good idea to try to name something the exact same thing as something else. (I mean equal fully-qualified names, including all namespaces.) If some library has already grabbed the obvious best name in the global namespace, you'll need to pick a different name.
You could put your class Thing in a namespace as Pete Becker suggests, and then use ::Thing to access Acme's Thing. That would be fine if you're prepared to always access your class through it's fully namespace-qualified name (e.g. My::Thing). It's tempting to try using My::Thing; or using namespace My;, but that won't work, because any translation unit that includes the definition of your class (e.g. via a header file you create) must necessarily pull Acme's Thing into the global namespace first (otherwise an "Undefined symbol" compilation error would occur when parsing the definition of My::Thing).
Is it really a C API? Try to extern "C" {} to whole included header to solve the linking problem.
namespace AcmesUglyStuff {
extern "C" {
#include <acme_stuff.h>
}
}
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;
}
In a header I have a setup like this
namespace NS {
typedef enum { GOOD, BAD, UGLY }enum_thing;
class Thing {
void thing(enum_thing elem);
}
}
and of course another cpp file that goes along with that header. Then I have a thread cpp file that contains main(). In this cpp file I use that enum to pass to the method thing().
using namespace NS;
int main() {
Thing t();
t.thing(BAD);
}
and of course I get other errors from G++ saying BAD was not declared. Any help on how I could overcome this error?
After correcting numerous little syntax errors in the sample code, it compiles just fine for me. Check that you've spelled the names correctly. Can you access the enum as NS::BAD? Perhaps you haven't included the correct header? Make sure you have
#include "FileWithEnum.h" at the top.
namespace NS {
typedef enum { GOOD, BAD, UGLY }enum_thing;
class Thing {
public:
void thing(enum_thing elem){}
};
}
using namespace NS;
int main() {
Thing t;
t.thing(BAD);
return 0;
}
Test it yourself:
http://codepad.org/Uw0XjOlF
Can you avoid using a typedef? Just do:
enum Foobar {good, bad, hello};
It should work. It does for me (the variant by Mystagogue should also work). I understand you had some other error messages ?
You probably just have to fix the header to be syntaxically correct, like putting a semi-colon at the end of class Thing, etc. When the header will be OK, the message about BAD not in namespace should also disappear.