Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does "using namespace xxx" not take effect on template functions?

Tags:

c++

namespaces

namespace ns1
{
    template <class T>
    void f(T)
    {
        cout << typeid(T).name() << endl;
    }
};

using namespace ns1;

namespace ns2
{
    void f(int)
    {
        cout << "int" << endl;
    }

    void test()
    {
        f(vector<int>()); // Error! 
        // Why not call ns1::f<vector<int>>(vector<int>()); ???
    }
};
like image 501
xmllmx Avatar asked Dec 15 '10 09:12

xmllmx


4 Answers

This has nothing to do with templates, but without name lookup.

This is what the standard says in 3.4/1 (name lookup) :

Name lookup shall find an unambiguous declaration for the name (see 10.2). Name lookup may associate more than one declaration with a name if it finds the name to be a function name; the declarations are said to form a set of overloaded functions (13.1). Overload resolution (13.3) takes place after name lookup has succeeded. The access rules (clause 11) are considered only once name lookup and function overload resolution (if applicable) have succeeded.

And in 3.4.1 (unqualified name lookup) :

name lookup ends as soon as a declaration is found for the name

In your case, f is an unqualified name. It is searched in the immediate scope, and in namespace ns2 where a declaration is found. Name lookup ends here, and overload resolution comes into play : there is no overload in the candidate set which matches the argument type std::vector<int>, so the program is ill-formed.

like image 198
icecrime Avatar answered Nov 03 '22 00:11

icecrime


Because when you're inside a namespace (ns2) it takes precedence over any others if names are unqualified.

like image 41
OrangeDog Avatar answered Nov 02 '22 23:11

OrangeDog


ns2 will take priority as that is the namespace you are currently in. Why should the compiler think that you really meant ns1::f() ?

like image 2
koan Avatar answered Nov 03 '22 00:11

koan


This should work :

namespace ns1
{
    template <class T>
    void f(T)
    {
        cout << typeid(T).name() << endl;
    }
};



namespace ns2
{
    using ns1::f;
    void f(int)
    {
        cout << "int" << endl;
    }

    void test()
    {
        f(vector<int>()); // Error! 
        // Why not call ns1::f<vector<int>>(vector<int>()); ???
    }
};
like image 1
mattanjah Avatar answered Nov 03 '22 00:11

mattanjah