I believe this short C++ code should compile without errors: class c; template<typename T> class tm { public: const T& g() const; }; namespace n { template <class T> int fn(const tm<T> &v) { return fn(v.g()); } int fn(const c *p); } int main() { tm<c *> v; return n::fn(v); } Instead, I get foo.cc: In function ‘int n::fn(const tm<T>&) [with T = c*]’: foo.cc:7: instantiated from here foo.cc:4: error: no matching function for call to ‘fn(c* const&)’ Here fn is being called recursively with an argument which depends on the template type, so it should be looked up at template instantiation time, not at template definition time. So the matching call should be found. By comparison, this code compiles without error: class c; template<typename T> class tm { public: const T& g() const; }; namespace n { int fn(const c *p); template <class T> int fn(const tm<T> &v) { return fn(v.g()); } } int main() { tm<c *> v; return n::fn(v); } This is not surprising, since the function declaration can now be seen at template definition time. However, this code also compiles without error: class c; template<typename T> class tm { public: const T& g() const; }; template <class T> int fn(const tm<T> &v) { return fn(v.g()); } int fn(const c *p); int main() { tm<c *> v; return fn(v); } Here the declaration is only available at template instantiation time, yet it works. So it seems to be me that there may be a bug related to namespaces when handling lookup of template dependent types. I haven't investigated further.
I don't think this is a bug. There are two clauses to the C++ standard about namelookup in templates. One applies where the definition. And the other applies to both definition and instaination but only for the namespace containing the type. Take the first case: class c; template<typename T> class tm { public: const T& g() const; }; namespace n { template <class T> int fn(const tm<T> &v) { return fn(v.g()); // we have one overloading function for fn, the current template fn // at definition } int fn(const c *p); } int main() { tm<c *> v; return n::fn(v); // when instationating this function fn, we look again at the overloading // set for fn but since c is defined in the global namespace, we don't see // the other fn in namespace n. } PR 2922/DR 197 describes this better than I can right now.
This is not a bug. 14.6.4.2 Candidate functions For a function call that depends on a template parameter, if the function name is an unqualified-id but not a template-id, the candidate functions are found using the usual look rules (3.4.1, 3.4.2) except that: -- For the part of the lookup using unqualified name lookup (3.4.1), only functions with external linkage from the template __DEFINITION__ context are found -- For the part of the lookup using associated namespaces (3.4.2), only functions declarations with external linkage found in either the template __DEFINITION__ context or the template __INSTANTIATION__ context are found. __BOLD__ is mine. So what this says that the functions that are chosen for this fn (in the first case) is either the template fn or a function which is associated with the namespace of the type, which is in this case is the global namespace (ADL does not look into nested namespaces). That explains the first case. The second case can be explained by this: the function fn is seen at the template __DEFINITION__ context which makes it valid code. The third case can be explained by this: The namespace associated with the type is the global namespace and there is a function fn that matches the arguments in that namespace at the template __INSTANTIATION__ context. Hopefully this explains why the first case is invalid code and why the rest are valid. One should note there is no associated namespace for fundumental types at least not yet, there is a Defect report about this to the C++ standard raising from DR 197.