Description
Today I've spent quite some time to discover why adding something like
namespace foo::detail { /* stuff */ }
in a header of mine was causing havoc in a seemingly unrealted translation unit (unrelated to the one I was compiling when I made the change). The error was along these lines, where innocent-header.hpp
is the only file I own:
error: 'FooBar' is not a member of 'foo::detail'; did you mean 'foo::bar::baz::detail::FooBar'?
The problem was a using directive:
- when compiling my TU, everything was fine;
- when compiling the other TU, my header ended up being included together with
- a header that had a using directive,
- and antoher header that made the mistake of leveraging that directive.
The failing translation unit was therefore looking like this:
// /* broken-header.hpp */
namespace foo {
namespace bar::baz::detail {
}
using namespace foo::bar::baz;
}
// /* innocent-header.hpp */
namespace foo::detail { /* stuff */ }
// /* thoughtless-header.hpp */
// #include "broken-header.hpp"
namespace foo::bar::baz {
namespace detail {
struct Foo {};
}
auto f() {
return foo::detail::Foo{};
}
}
int main() {
foo::f();
}
where the order of inclusion of broken-header.hpp
and innocent-header.hpp
is irrelevant.
I wouldn't say that thoughtless-header.hpp
is innocent, but they could have made the mistake of writing foo::detailFooBar
instead of foo::bar::baz::detail::FooBar
just because they've distractedly Tab-completed with their IDE.
But I think that the real problem is still the using namepspace
.
So why shouldn't we change the title of SF.7 the following?
Don’t write using namespace in a header file