This code reproduces the problem with gcc-4.x, but compiles fine with prior versions of gcc and with other compilers. The error output differs depending on what exactly is parsed, but I believe this example illustrates the general change in behavior.
FILE: header1.h ------------------------------------------ #ifndef _INCLUDED_Header1_H #define _INCLUDED_Header1_H #include <string> namespace N { const std::string & resolveName(const int &) { static const std::string & name = "int"; return name; } const std::string & getName(const int & v) { return resolveName(v); } template<typename ValueType> const std::string & getName(const ValueType & v) { return resolveName(v); } } #endif//_INCLUDED_Header1_H ------------------------------------------ FILE: main.cpp ------------------------------------------ #include <string> #include "header1.h" class A { public: A() { } ~A() { } }; namespace N { const std::string & resolveName(const A &) { static const std::string name = "A"; return name; } } int main(int, char **) { int result = 0; const std::string & resultName = N::getName(result); A a; const std::string & name = N::getName(a); // <- fails to find N::resolveName(const A &) // while processing // template<typename ValueType> const std::string & getName(const ValueType &) from // header1.h unless the above N::resolveName(const A &) is declared BEFORE // header1.h is included, though the point of resolution appears AFTER // both header1.h is included and N::resolveName(const A&) is defined. // This behavior is new to gcc-4 and not present in most other compilers // including gcc prior to version 4. return result; } ------------------------------------------ g++ -c main.cpp header1.h: In function ‘const std::string& N::getName(const ValueType&) [with ValueType = A]’: main.cpp:26: instantiated from here header1.h:21: error: invalid initialization of reference of type ‘const int&’ from expression of type ‘const A’ header1.h:8: error: in passing argument 1 of ‘const std::string& N::resolveName(const int&)’ Changing main.cpp to include header1.h AFTER resolveName(const A &) is declared works around this issue: FILE: main.cpp ------------------------------------------ #include <string> class A { public: A() { } ~A() { } }; namespace N { const std::string & resolveName(const A &) { static const std::string name = "A"; return name; } } #include "header1.h" int main(int, char **) { int result = 0; const std::string & resultName = N::getName(result); A a; const std::string & name = N::getName(a); return result; } ------------------------------------------ In this contrived example, the workaround is straightforward and easy to implement. In a larger codebase, the workarounds are difficult to implement or even discern. I'm not sure what happens if there is some complex cyclic dependency introduced now that parsing order is significant. In my case specifically, I use namespaces to arbitrarily extend functionality for client code as long as the user declares new methods in scope of the type they are compiling. (e.g. serializing a complex, user-defined type). Does the standard require this behavior, or is this an optimization that has broken code that does not have gcc-4 correct ordering of its headers? -- Summary: template fails to resolve names even when the name is in scope before the call point Product: gcc Version: 4.1.2 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: logicle at live dot com GCC build triplet: linux 2.6.23 x86_64 GCC host triplet: linux 2.6.23 x86_64 GCC target triplet: linux 2.6.23 x86_64 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34322