To summarize, no, using-declarations in a header are not ok, even within a namespace, for 2 reasons. Further, using-declarations within a namespace in a non-header are error-prone or pointless (see end). Using-declarations in a header are not ok because:
- They introduce a name into the namespace, which affects all files that include the header.
- They introduce only declarations for the name that have already been seen, which means that behavior depends on order of includes!
In your example, this means that:
- Within
MyNamespace
, vector
now may resolve to boost::numeric::ublas::vector
, for any files that include this header: it "pollutes" the MyNamespace
namespace.
- Which
boost::numeric::ublas::vector
declarations are imported depends on what declarations appear before this using-declaration, which depends on the order of includes in the file that includes this header, and all of its includes (properly, the order of declarations in the translation unit, after preprocessing).
Per your comment of May 30 '11 at 11:51 you actually want behavior 1, but this doesn't work, due to problem 2. You can get the desired behavior by having a separate header that is included after all others (and fully qualifying the name in other headers). However, this is fragile and thus discouraged, preferably being reserved only when transitioning to namespaces:
//--- file myheader.hpp ---
#include <boost/numeric/ublas/vector.hpp>
namespace MyNamespace {
::boost::numeric::ublas::vector MyFunc(::boost::numeric::ublas::vector in);
}
//--- file myproject_last.hpp ---
namespace MyNamespace {
using ::boost::numeric::ublas::vector;
}
//--- file myproject.cpp ---
#include "myheader.hpp"
// ...other includes
#include "myproject_last.hpp"
See GotW #53: Migrating to Namespaces for details, this workaround, and advice: "Namespace using declarations should never appear in header files."
It is possible to avoid problem 1 by adding an unnamed namespace around the using-declaration (to prevent those names from being visible) and then another one outside the unnamed namespace (to make the desired name itself visible), but that still suffers from problem 2 and uglifies the header:
//--- file myheader.hpp ---
#include <boost/numeric/ublas/vector.hpp>
namespace MyNamespace {
namespace {
using ::boost::numeric::ublas::vector;
vector MyFunc(vector in);
}
using MyFunc; // MyNamespace::(unique)::MyFunc > MyNamespace::MyFunc
}
Due to these problems, you should only use using-declarations in non-header (.cc/.cpp) files: this doesn't affect other files, so problem 1 is avoided; and all headers have been included, so problem 2 is avoided. In this case it's a matter of taste whether you put them in a namespace or not, since they don't affect other files; it's safest to always use fully qualified names on in the using-declaration itself (absolute, starting with ::
).
Simplest is to put all using-declarations at the top of the file, after the includes, but outside of any namespaces: this is safe, unambiguous, easy to read, and allows the names to be used throughout the file. Some common deviations:
- Using-declaration within a function (or struct or class or nested block): fine. This minimizes scope and is just a matter of taste: using-declaration is close to use (legibility win), but they are now scattered throughout the file (legibility loss).
Using-declaration with a relative name within a (named) namespace: error-prone. This is more concise and adds some clarity (related names used in the namespace to which they relate), but is potentially ambiguous (just like includes with relative paths), and is safer to avoid:
using ::foo::bar;
namespace foo { ... }
namespace foo {
// Implicitly ::foo:bar, could be ::bar, or ::other::foo::bar.
using bar;
}
Using-declaration with an absolute name within a named namespace: pointless. This introduces the name only into the namespace, but you shouldn't care, since you shouldn't be including the .cc/.cpp file:
namespace foo {
using ::bar;
}
Using-declaration within an unnamed namespace: pointless, slightly dangerous. For example, if you have a function in an unnamed namespace, say an implementation detail, then you can have a using-declaration for its return type or param types. This introduces the name into just that namespace (so can't be referenced from other files), but again, you shouldn't care, since you shouldn't be including the .cc/.cpp file (unnamed namespaces are especially for avoid name clashes at link time, which isn't applicable here: it's just a compile-time alias). Worse, it introduces ambiguity if that name already does exist!