tags:

views:

267

answers:

7

I am using two large libraries (GUI & network) and I can happily do

using namespace FirstLib;
using namespace SecondLib;

Except for 1 single class called Foobar where names clash.

I my code, I do not use FirstLib::Foobar. Is there a way to say "in my code, whenever you see Foobar, think SecondLib::Foobar ?

+1  A: 

You have to pick one of these namespaces and get rid of the 'using', and explicitly call out all the class names. C# has a way around this, but C++ does not afaik...

Paul Betts
+2  A: 

You've basically answered your own question. You must explicitly say which class you want to use, so you must do SecondLib::Foobar whenever you use that class.

SoapBox
A: 

Have you tried:

using SecondLib::Foobar;

?

fbrereto
It does not work.
Gaspard Bucher
+4  A: 

using namespace is evil! Namespaces were made to prevent such problems as you have! But that said, try:

using namespace FirstLib;
using namespace SecondLib;
using SecondLib::Foobar;

or even (for some compilers):

using namespace FirstLib;
using namespace SecondLib;
typedef SecondLib::Foobar Foobar;
Kornel Kisielewicz
+1 However, when evilizing use of any aspect of C++, it's good to explain why something may be considered as such, otherwise it's confusing. Or at least referring to the C++ FAQ: http://www.parashift.com/c++-faq-lite/big-picture.html#faq-6.15
mloskot
@mloskot -- thanks for the tip -- nice link, I'll be linking my "evil"s to it if no better link will be handy :P
Kornel Kisielewicz
Neither of those seems to make any difference with GCC, nor Comeau online. `namespace a { struct X {};} namespace b { struct X {}; } using namespace a; using namespace b; using b::X; /*typedef b::X X;*/ int main() { X x; }`
UncleBens
@UncleBens - put using ::b::X; inside main function, not globally.
mloskot
Thanks for the clarification. - BTW, aren't namespaces there so you could disambiguate names *if you need to*? If you have two libraries that declare the same names globally, **then** you have a real problem. A common technique is library-specific prefixes on all names. The advantage of namespaces is that *you can drop the "prefix" where it doesn't add anything*.
UncleBens
@UncleBens The real advantage of namespaces is in modularization of code and Argument Dependant Lookup (ADL, Koenig) support. If two libraries define the same names globally, one of solutions can be to include header inside namespace WrapOldStuffNS {} block, however it may cause other problems like linker errors.
mloskot
UncleBens
`using SecondLib::Foobar` does not work with gcc (same ambiguity)
Gaspard Bucher
+1  A: 

I don't think there's a way of excluding names. You either bring in the whole lot, or each one individually. Even when you bring in the whole lot, you can always disambiguate conflicting names by qualifying them fully.

However, you could use typedef to rename the offending class:

typedef Lib2::FooBar FooBaz;

And I guess, with a conflicting function, you could use a function pointer to "rename" the conflicting one.


I guess it's kind of a non-solution. I can understand the occasional motivation to use using declarations - sometimes there are indeed many different names that you'll use all over the place - but if just one is conflicting: be explicit. It would be confusing to anyone familiar with the libraries anyway, seeing that both namespaces are imported.

Also, using declarations respect scope: you can make one namespace visible in one function, but not the other namespace - assuming you don't even use it in that function.

UncleBens
`typedef Lib2::Foobar Foobar` does not work either with gcc.
Gaspard Bucher
It is Fooba *z*. Kornel's answer is missing that the specific using declaration should be in function, not global scope (I assume ordinary scope rules work: things in an inner scope hide things in the outer scope).
UncleBens
Sorry, my mistake, it's just that another answer was proposing the typedef without any name change in the class name which obviously doesn't work.
Gaspard Bucher
A: 

If you load all elements from both namespace to current scope by use of using namespace directove:

using namespace FirstLib;
using namespace SecondLib;

and there is potential that some of the names in those namespace may clash, then you need to tell compiler explicitly which of the element you want to use, in current scope, by use of using declaration:

using SecondLib::Foobar;

As the C++ standard says:

7.3.3 The using declaration

1 A using-declaration introduces a name into the declarative region in which the using-declaration appears. That name is a synonym for the name of some entity declared elsewhere.

This line requests compiler to think SecondLib::Foobar whenever it sees Foobar for the rest of current scope in which the using declaration was used.

The using directive and declaration is very helpful, but they may cause problems as the one you're dealing with. So, it's a good idea to narrow use of any form of using to minimal scope possible. You can use the directive using namespace in scope of other namespace

namespace MyApp {
   using namespace ::SecondLib;
}

or even a function. The same applies to using declaration. So, it's a good idea to narrow the scope of use of any of them:

void foo()
{
   ::SecondLib::Foobar fb;
}

It may seem tedious, but it is only when you type, though you most likely use intellisense-enabled editor, so cost is really small, but benefits are large - no confusions, readable code, no compilation issues.

It's also a very good idea to NOT to use using namespace in header scope. See Header files usage - Best practices - C++

My own tip: do use full qualification whenever you need to use any of these types

mloskot
A: 

It's strange nobody suggested to replace the full namespace use by the list of used class names. This solution is even in the C++faq (where I should have thought to look first).

If we cannot say

include all FirstLib, but remove SecondLib::Foobar

We can use using-declarations of the exact elements we need:

using FirstLib::Boids;
using FirstLib::Life;
// no using FirstLib::Foobar...
Gaspard Bucher