Reputation: 63787
I would like to understand the namespace qualified name lookup. I am trying to leverage the following
3.4.3.2.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(N_i,m) for all namespaces N_i nominated by using-directives in X and its inline namespace set.
to provide a fallback mechanism for a name iff it does not exist in the standard namespace. The following program exemplifies what I am envisaging to achieve
#include <type_traits>
namespace foo
{
template<class Ty>
struct remove_extent
{
typedef Ty type;
};
}
namespace fallback
{
using namespace std;
}
namespace fallback
{
using namespace foo;
}
template<typename Ty>
struct Bar
{
typename fallback::remove_extent<Ty>::type var;
};
int main()
{
Bar<int[]> var;
}
For the first declaration
namespace fallback
{
using namespace std;
}
S'(fallback, remove_extent)
is an empty set so S(fallback, remove_extent)
is the union of S(std, remove_extent).
For the second declaration
namespace fallback
{
using namespace foo;
}
S'(fallback, remove_extent)
is non-empty so S(fallback, remove_extent) = S'(fallback, remove_extent) = S(std, remove_extent)
but my compiler thinks otherwise and complains
1>source.cpp(21): error C2872: 'remove_extent' : ambiguous symbol
1> could be 'source.cpp(6) : foo::remove_extent'
1> or 'c:\program files (x86)\microsoft visual studio 11.0\vc\include\type_traits(331) : std::remove_extent'
So obviously my understanding is wrong. Why does the compiler includes the name remove_extent
from foo?
Upvotes: 0
Views: 231
Reputation: 62995
For the second declaration ...
S'(fallback, remove_extent)
is non-empty
No, it isn't:
namespace fallback
{
using namespace std;
}
After this point, S'(fallback, remove_extent)
is empty, so S
is S(std, remove_extent)
.
namespace fallback
{
using namespace foo;
}
After this point, S'(fallback, remove_extent)
is still empty (i.e. there's still no declaration of a remove_extent
directly in fallback
), so S
is now the union of S(std, remove_extent)
and S(foo, remove_extent)
.
template<typename Ty>
struct Bar
{
typename fallback::remove_extent<Ty>::type var;
};
When we get to this point, there are two entities named remove_extent
in fallback
(one from std
and one from foo
, neither declared directly in fallback
), so the compiler correctly tells you that the name is ambiguous.
Upvotes: 4