Andrey Tarasevich
2024-09-07 18:24:31 UTC
Hello
It is illegal to just flat-out declare a class and a namespace with
identical names in the same scope
namespace N {}
class N {}; // <- Not allowed
However, one can try to circumvent the direct restriction by means of
using-directive or using-declaration
#include <iostream>
namespace N
{
void foo() { std::cout << "namespace" << std::endl; }
}
namespace X
{
struct N
{
static void foo() { std::cout << "class" << std::endl; }
};
}
using X::N;
// or
// using namespace X;
int main()
{
N::foo();
}
GCC is perfectly happy with either version of this code (both
using-declaration and using-directive versions are OK). It simply
resolves the call to the "namespace" version of `foo()`.
Clang issues an error: it complains about the call being ambiguous. I.e.
the error is issued at the point of the call.
MSVC++ issues an error for `using X::N;` at the point of
using-declaration: it basically says that `N` already exists in this
scope. But if we switch to `using namespace X;` version, MSVC++ will
exhibit Clang-like behavior: complain about ambiguity at the point of
the call.
So, who is right here?
--
Best regards,
Andrey
P.S. We can rewrite `main` as
int main()
{
using T = struct N;
T::foo();
}
This will keep both GCC and Clang happy and direct the call to the
"class" version of `foo()`. It will work in both using-declaration and
using-directive versions of the code
This will work in MSVC++ as well, but obviously only with
using-directive version (since using-declaration triggers an error earlier).
Again, who is right here?
It is illegal to just flat-out declare a class and a namespace with
identical names in the same scope
namespace N {}
class N {}; // <- Not allowed
However, one can try to circumvent the direct restriction by means of
using-directive or using-declaration
#include <iostream>
namespace N
{
void foo() { std::cout << "namespace" << std::endl; }
}
namespace X
{
struct N
{
static void foo() { std::cout << "class" << std::endl; }
};
}
using X::N;
// or
// using namespace X;
int main()
{
N::foo();
}
GCC is perfectly happy with either version of this code (both
using-declaration and using-directive versions are OK). It simply
resolves the call to the "namespace" version of `foo()`.
Clang issues an error: it complains about the call being ambiguous. I.e.
the error is issued at the point of the call.
MSVC++ issues an error for `using X::N;` at the point of
using-declaration: it basically says that `N` already exists in this
scope. But if we switch to `using namespace X;` version, MSVC++ will
exhibit Clang-like behavior: complain about ambiguity at the point of
the call.
So, who is right here?
--
Best regards,
Andrey
P.S. We can rewrite `main` as
int main()
{
using T = struct N;
T::foo();
}
This will keep both GCC and Clang happy and direct the call to the
"class" version of `foo()`. It will work in both using-declaration and
using-directive versions of the code
This will work in MSVC++ as well, but obviously only with
using-directive version (since using-declaration triggers an error earlier).
Again, who is right here?