Hi,
There are two types of name hiding in c++:
I'm interested to know about how name hiding interacts with using-directives when unqualified name lookup is performed.
For the first type of name hiding the behaviour is quite clear. This is because [basic.scope.hiding]p1 has been reformulated in terms of the rules in the section [basic.lookup.unqual]
http://eel.is/c++draft/basic.lookup.unqual
The same has not been done for the second type of name hiding. So the following question now arises:
*) How should this second type of name hiding interact with unqualified name lookup that involves using-directives?
"A using-directive specifies that the names in the nominated namespace can be used in the scope in which the using-directive appears after the using-directive. During unqualified name lookup ([basic.lookup.unqual]), the names appear as if they were declared in the nearest enclosing namespace which contains both the using-directive and the nominated namespace. [ Note: In this context, “contains” means “contains directly or indirectly”. — end note ]"
Applying the
as if part of this rule to [basic.scope.hiding]p1 gives consistency with the rules in the section [basic.lookup.unqual]. This application is also consistent with [basic.scope.hiding]p4
http://eel.is/c++draft/basic.scope.hiding#4 So this looks promising.
Because of this I think we can answer the question *) by similarly applying the as if part of [namespace.udir]p2 to [basic.scope.hiding]p2. This application is also consistent with [basic.scope.hiding]p4. I think this is also the most natural and least complex interpretation of the c++ standard.
The problem however is that Clang and GCC does not make the same interpretation as me. For example:
namespace N { static int i = 1; }
namespace M { struct i {}; }
using namespace M;
using namespace N;
int main() { sizeof(i); }
According to my interpretation this program should be well-formed and i should be looked up as the integer variable. Both Clang and GCC disagree with this by giving a name lookup ambiguity.
In the case of Clang this more complex interpretation leads to the following bug:
namespace N { static int i = 1; }
namespace M { struct i {}; }
namespace P {
using N::i;
using M::i;
}
namespace Q { using M::i; }
using namespace P;
using namespace Q;
int main() { sizeof (i); }
Gives no errors, but change
using namespace P;
using namespace Q;
into
using namespace Q;
using namespace P;
and we get name-lookup ambiguity error. GCC is at least consistent here.
What I want with this post is to get a second option about the way I interpret the c++ standard since at least two compilers seems to disagree with me (even if one of the is obviously buggy in its interpretation of the standard).
/Anders