3

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 ?

Anna B
  • 5,997
  • 5
  • 40
  • 52
  • 5
    Don't use `using namespace`. It was invented to protect you from your very problem, and it's abhorred because it re-introduces the problem, like you have. Use a namespace alias if you find it too long to type. – GManNickG Jan 30 '10 at 01:00
  • 1
    I'm not a very big fan of dos and donts. Use cases are never black or white like in school books. In fact, the solution I propose (Use a using-declaration) is in the http://www.parashift.com/c++-faq-lite/coding-standards.html#faq-27.5 – Anna B Jan 30 '10 at 10:05

7 Answers7

6

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
  • 55,802
  • 15
  • 111
  • 149
  • 3
    +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 Jan 30 '10 at 00:52
  • @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 Jan 30 '10 at 00:55
  • 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 Jan 30 '10 at 01:00
  • 1
    @UncleBens - put using ::b::X; inside main function, not globally. – mloskot Jan 30 '10 at 01:11
  • 1
    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 Jan 30 '10 at 01:15
  • @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 Jan 30 '10 at 01:25
  • Isn't ADL basically a confusing work-around for the problem that namespaces didn't fit nicely into the language (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2103.pdf)? I can't pretend this is a part of C++ I understand (but it seems I'm not alone: http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=286) – UncleBens Jan 30 '10 at 01:56
  • `using SecondLib::Foobar` does not work with gcc (same ambiguity) – Anna B Jan 30 '10 at 09:40
  • "`using namespace` is evil!" Have you notified the maintainers of the C++ standard, so that they know to remove it from the next version? – Pulseczar Aug 26 '16 at 21:42
3

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...
Anna B
  • 5,997
  • 5
  • 40
  • 52
2

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
  • 20,457
  • 3
  • 51
  • 87
1

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...

Ana Betts
  • 73,868
  • 16
  • 141
  • 209
1

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
  • 40,819
  • 6
  • 57
  • 90
  • 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 Jan 30 '10 at 10:34
  • 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. – Anna B Jan 30 '10 at 13:55
0

Have you tried:

using SecondLib::Foobar;

?

fbrereto
  • 35,429
  • 19
  • 126
  • 178
0

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

Community
  • 1
  • 1
mloskot
  • 37,086
  • 11
  • 109
  • 136