Are all using directives viewed the same way as using namespace std?
Asked Answered
L

1

0

I've easily gotten myself into the habit of prefixing standard identifiers with std:: instead of sticking in a using namespace std;. However, I've started getting into C# and I've noticed that it's very normal to add in whatever using directives are necessary, i.e., you'd see:

using System;
Console.Write("foo");

instead of:

System.Console.Write("foo");

Apparently, as I found out from a C# question on this topic, that usage comes from the fact that individual system namespaces in C# are much, much smaller than std is in C++, and therefore eliminates the problems associated with name clashes, as there is much less likelihood (and you can just find-replace it with a fully qualified name if a library updates with a name-clash), and eliminates the problems associated with a crapload of Intellisense options appearing, as the namespaces are small enough to handle.

The question, then, is that if these are the standing reasons to make use of using directives in C#, is the same true for C++? Is it generally acceptable to apply this to smaller third-party namespaces, as well as your own smaller namespaces?

Now I realize that this might cause a bit of controversy, I want to take this moment to ask that it doesn't turn into an argument. A good answer should include a basis, i.e., advantages or disadvantages, and how using one way over the other really makes a worthwhile difference.

The reason I ask this is to clear up the issue, and possibly remove the notion that using directives in C++ have to be a bad thing. Sure longer namespace names can be cut down with a namespace alias if necessary, and fully qualified names can still be used if needed, but sometimes a using directive greatly eases accessing some members such as user-defined literal operators, which, to my knowledge, have no form of ADL, meaning that you either have to use a using directive, or call the operator method by the function syntax, defeating the whole purpose of using the operator in the first place.

For example, I had a namespace (that includes a structure representing a keyboard key, along with a literal suffix as a readable alternate means of access:

"caps lock"_key.disable();

The problem here is that unless you have previously inserted using namespace Whatever; or using Whatever::operator"" _key;, the code won't compile, which is bad news for the user.

Using directives have obvious problems when std is involved or when used in such a way in a header that they bring unwanted extras for the user of that header, but is it justified to use them for other namespaces when contained within a smaller scope than whatever includes a header? The keystrokes saved from not having to type each qualifier each time do add up, and with today's Intellisense capabilities, finding out which namespace an unqualified identifier belongs to is as easy as mousing over it.

Luxor answered 4/9, 2012 at 3:55 Comment(2)
Remember that C# does not have the problems (features) with header files that C++ does so a whole class of problems is eradicated there.Overleap
@LokiAstari, A very good point. Isn't C++ trying to overhaul the #include system for the next update to the language?Luxor
E
2

I think the rules about using declarations in C++ are rather simple:

  1. NEVER write "using namespace anything;" in the global scope of a header, especially one that is likely to be reused by other programs (e.g. when writing a library). It pollutes the global scope of all subsequent headers with the symbols of this namespace, which defeats the entire purpose of namespaces, and can create unforeseen name clashes later on.
  2. In the .cpp files and inner scopes of headers (e.g. inline function scopes), you can be "using" whatever namespaces you want, as it won't affect any other file. Just do whatever is more convenient for you and try to be reasonably consistent within a project.

EDIT: for the _key problem, simply define this operator in its own namespace and tell users to import it. This way they won't need to type out the operator declaration.

namespace something {
class key { ... };
}
namespace key_suffix {
something::key operator"" _key() { ... }
}

// user code
void some_function() {
    using namespace key_suffix;
    "caps lock"_key.doSomething();
}
Eat answered 4/9, 2012 at 4:9 Comment(4)
I definitely agree with #1, but for #2, there are problems existing with that (see this question). Are those problems prominent enough in namespaces other than std to influence programmers not to import the whole thing into their cpp file?Luxor
These problems are more likely to happen if you import more than one namespace. To avoid this, simply import at most one namespace in each scope. There's no 100% bulletproof way to prevent naming clashes - someone could always reuse the same namespace name for 2 distinct libraries. Fortunately a naming clash is rarely time consuming to fix, as a series of simple text search and replaces will be enough to make 99% of code compile again.Thurible
I would say #2 is only acceptable in really small scopes, at which point it may become useless anyway. I have only seen problems coming from using it, and no benefits whatsoever.Autocatalysis
One problem we have seen is that C++11 has adopted many parts of the Boost library. "Suddenly" we have lots of name clashes.Peeve

© 2022 - 2024 — McMap. All rights reserved.