Topic: template and type-dependent name resolution


Author: Michael Norrish <michael.norrish@nicta.com.au>
Date: Mon, 21 May 2007 23:26:20 CST
Raw View
I'm confused by g++ 4.0.3's behaviour on the following program (and
its variants, indicated by comments):

----------------------------------------------------------------------
#include <iostream>
using namespace std;

namespace m0 {
   namespace m {
     class C { public: int x; };
   }
}

namespace p {
   template <class T> class Foo {
   public:
     T x;
     int g() { return f(x); }
   };
}

int h()
{
   p::Foo<m0::m::C> foo;
   return foo.g();
}

int main()
{
   cout << h() << endl;
   return 0;
}

namespace m0 {
   // this works
   namespace m {
     int f (C &c) { cout << "Yay\n"; return 1; }
   }
   // but this does not
   // int f(m::C &c) { cout << "Urk\n"; return 2; }
}

// this would also work (if m0::m::f isn't also around - if both are
// present, there is an ambiguous overloading error)
// int f(m0::m::C &c) { cout << "Cool\n"; return 3; }
----------------------------------------------------------------------

The first f (in m0::m) is found because it's in the same namespace as
the declaration of C.

The last f (commented out), is found by name resolution of the
template body, because it appears "in the namespace" of the template
definition.  (Indeed, you can mask it by putting a declaration of f
into namespace p.)  Of course, the last f is actually in the global
namespace, not in p, but p 'inherits' it.

The second f (commented out) is not found however, and this confuses
me.  Why is the rule different for the namespaces associated with the
class argument as opposed to the template definition?  I don't get any
inspiration from reading the language of 3.4.2 para 2, and 14.6.4.2)

Or is g++ just incorrect?

Thanks,
Michael.


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: AlbertoBarbati@libero.it (Alberto Ganesh Barbati)
Date: Tue, 22 May 2007 22:44:37 GMT
Raw View
Michael Norrish ha scritto:
>
> The first f (in m0::m) is found because it's in the same namespace as
> the declaration of C.
>
> The last f (commented out), is found by name resolution of the
> template body, because it appears "in the namespace" of the template
> definition.  (Indeed, you can mask it by putting a declaration of f
> into namespace p.)  Of course, the last f is actually in the global
> namespace, not in p, but p 'inherits' it.
>
> The second f (commented out) is not found however, and this confuses
> me.  Why is the rule different for the namespaces associated with the
> class argument as opposed to the template definition?  I don't get any
> inspiration from reading the language of 3.4.2 para 2, and 14.6.4.2)
>
> Or is g++ just incorrect?
>

I believe g++ is correct. 3.4.2/2 says:

"If T is a class type (including unions), its associated classes are:
the class itself; [...]. Its associated namespaces are the namespaces
in which its associated classes are defined."

m0::m::C is defined in m0::m. Even if m0::m is nested in m0, you can't
say that m0::m::C is defined in m0. (If you are not convinced about
that, consider that, in the scope of namespace m0, an unqualified name C
won't refer to m0::m::C.) So the list of associated namespaces contains
m0::m but not m0 and therefore m0 is not searched during ADL.

HTH,

Ganesh

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]