I realize this is more about new code than about refactoring existing code, but I like using a special header called X_fwd.hpp
for such cases.
// X_def.hpp
namespace B
{
struct X {};
}
namespace A
{
// NOT: using namespace B; // does not participate in ADL!
typedef ::B::X X; // OR: using ::B::X;
}
// X_fwd.hpp
namespace A { struct X; }
// some file needing declaration of X
#include <X_fwd.hpp>
This makes it a lot easier to find forward declarations, and also to change them after the fact, because the change is isolated in one place only (DRY...).
NOTE1: AFAIK, there is no technical difference between using Peter Wood's answer of a typedef
and your using
declaration. Note that a using
directive using namespace B;
could cause trouble because these are ignored by Argument-Dependent-Lookup. Even worse, some of your code might then even silently call the wrong function overload because you are not pulling in the new namespace B
anymore!
NOTE2: In the comments to the question, an Ideone example was given. This nicely illustrates a subtlety about name lookup inside namespaces: to quote from the draft Standard, section 3.4.3.2 Namespace members [namespace.qual], clause 2
For a namespace X and name m, the namespace-qualified lookup set S(X,
m) is defined as follows: Let S'(X, m) be the set of all declarations
of m in X and the inline namespace set of X (7.3.1). If S'(X, m) is
not empty, S(X, m) is S'(X, m); otherwise, S(X, m) is the union of
S(Ni, m) for all namespaces Ni nominated by using-directives in X and
its inline namespace set.
This explains the following tricky ambiguity
namespace A
{
struct X1{};
struct X2{};
}
namespace B
{
using A::X1; // OK: lookup-set is both namespace A and B, and a single unique name is found (at this point!)
struct X1; // OK: lookup-set is namespace B, and a single unique name is found
struct X2; // OK: lookup-set is namespace B, and a single unique name is found
using A::X2; // error: lookup-set is both namespace A and B, and no unique name is found (at this point!)
}
So the validity of having both a direct declaration and a using-declaration with the same name inside a namespace is order-dependent. Hence the convenience of a single declaration in a fwd header file.
fwd.h
is notdef_fwd.h
, that is, a header whose entire intent is to forward declare some other header names? – Sackiosfwd
), Boost (all over the place), et. al. – SackX
moved to an existing namespaceB
or wasnamespace A
renamed toB
? In the latter case, could you possibly use namespace aliases? – DosiA
still exists. – Ariosto