Monday, 22 May 2017

c++ - using std:: v.s. using std namespace




Two ways to use the using declaration are



using std::string;
using std::vector;


or



using namespace std;



which way is better?



=========Satisfactory Answer Below=============



In short, using declarations within functions are harmless provided locally scoped care is given whereas global using declarations are dangerous as they could cause namespaces to intersect, thereby confusing the compiler.




Often we like to use every name from a namespace without

qualification. That can be achieved by providing a using-declaration
for each name from the namespace, but that's tedious and requires
extra work each time a new name is added to or removed from the
namespace. Alternatively, we can use a using-directive to request that
every name from a namespace be accessible in our scope without
qualification. [...] [...] Using a using-directive to make names from
a frequently used and well-known library available without
qualification is a popular technique for simplifying code. This is the
technique used to access standard-library facilities throughout this
book. [...] Within a function, a using-directive can be safely used as

a notational convenience, but care should be taken with global
using-directives because overuse can lead to exactly the name clashes
that namespaces were introduced to avoid. [...] Consequently, we must
be careful with using-directives in the global scope. In particular,
don't place a using-directive in the global scope in a header file
except in very specialized circumstances (e.g. to aid transition)
because you never know where a header might be #included.




Credit to Jonathan Wakely for the quote.



Answer



It depends.



If you want to inject a single name into another scope, the using-declaration is better, e.g.



namespace foolib
{
// allow vector to be used unqualified within foo,
// or used as foo::vector
using std::vector;


vector vec();

template struct Bar { T t; };

template
void swap(Bar& lhs, Bar& rhs)
{
using std::swap;
// find swap by ADL, otherwise use std::swap

swap(lhs.t, rhs.t);
}
}


But sometimes you just want all names, which is what a using-directive does. That could be used locally in a function, or globally in a source file.



Putting using namespace outside a function body should only be done where you know exactly what's being included so it's safe (i.e. not in a header, where you don't know what's going to be included before or after that header) although many people still frown on this usage (read the answers at Why is "using namespace std" considered bad practice? for details):



#include 

#include
#include "foolib.h"
using namespace foo; // only AFTER all headers

Bar b;


A good reason to use a using-directive is where the namespace only contains a small number of names that are kept intentionally segregated, and are designed to be used by using-directive:



#include 

// make user-defined literals usable without qualification,
// without bringing in everything else in namespace std.
using namespace std::string_literals;
auto s = "Hello, world!"s;


So there is no single answer that can say one is universally better than the other, they have different uses and each is better in different contexts.



Regarding the first usage of using namespace, the creator of C++, Bjarne Stroustrup, has this to say in §14.2.3 of The C++ Programming Language, 4th Ed (emphasis mine):





Often we like to use every name from a namespace without qualification. That can be achieved by providing a using-declaration for each name from the namespace, but that's tedious and requires extra work each time a new name is added to or removed from the namespace. Alternatively, we can use a using-directive to request that every name from a namespace be accessible in our scope without qualification. [...]
[...] Using a using-directive to make names from a frequently used and well-known library available without qualification is a popular technique for simplifying code. This is the technique used to access standard-library facilities throughout this book. [...]
Within a function, a using-directive can be safely used as a notational convenience, but care should be taken with global using-directives because overuse can lead to exactly the name clashes that namespaces were introduced to avoid. [...]
Consequently, we must be careful with using-directives in the global scope. In particular, don't place a using-directive in the global scope in a header file except in very specialized circumstances (e.g. to aid transition) because you never know where a header might be #included.




To me this seems far better advice than just insisting it is bad and should not be used.


No comments:

Post a Comment

c++ - Does curly brackets matter for empty constructor?

Those brackets declare an empty, inline constructor. In that case, with them, the constructor does exist, it merely does nothing more than t...