Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Namespace having the same name as contained class, ok for gcc, not ok for clang

Consider the code:

template<typename T> 
class Foo{};

namespace X
{
    class X{};
}

using namespace X; // now both class X and namespace X are visible
Foo<X::X> f()
{
    return {};
}

int main() {}

gcc5.2 compiles the code with no errors whatsoever. However clang spits the error:

error: 'X' is not a class, namespace, or enumeration Foo f()

error: reference to 'X' is ambiguous

Is the code syntactically valid, according to the C++ standard? Or is just a gcc bug? Removing the qualified name X::X and using Foo<X> instead makes gcc choke also

error: template argument 1 is invalid Foo f()

like image 246
vsoftco Avatar asked Sep 26 '22 09:09

vsoftco


2 Answers

[namespace.udir]/6:

If name lookup finds a declaration for a name in two different namespaces, and the declarations do not declare the same entity and do not declare functions, the use of the name is ill-formed.

For the first X in X::X, both the namespace and the class are considered. However, the name of the namespace resides in the global namespace while the class resides in namespace X; Hence the above quote applies, Clang is therefore correct. (This also occurs when just writing X, clearly).

::X removes this ambiguity. Lookup does not proceed into the namespace anymore. [namespace.qual]/2:

For a namespace X and name m, the namespace-qualified lookup set S(X, m) is defined as follows: Let S0(X, m) be the set of all declarations of m in X and the inline namespace set of X (7.3.1). If S0(X, m) is not empty, S(X, m) is S0(X, m); otherwise, […]

Here, X is the global namespace and m is "X". Clearly, the declaration of our namespace is found, so lookup is definite here.

like image 200
Columbo Avatar answered Sep 29 '22 05:09

Columbo


Not a complete answer but that is a clear situation that shows even declaring using namespace, for objects with the same name as the namespace you need to declare the namespace.

#include <iostream>
#include <string>

namespace test
{
    void function1(void){std::cout << "Function inside the namespace" << std::endl;}

    class test
    {
    public:
        static void function1(void){std::cout << "Function inside the class" << std::endl;}    
    };
};

using namespace test;

int main()
{
    function1();

    test::function1();

    test::test::function1();
}

Output (GCC 4.9.2)

"Function inside the namespace"
"Function inside the namespace"
"Function inside the class"
like image 36
Captain Wise Avatar answered Sep 29 '22 06:09

Captain Wise