I have run into a compiler error with gcc 4.x that I am trying to understand whether my code is wrong or the compiler has a bug.
FYI: 4.1.2 is shown in the compiler output below, but I have had the same results with 4.2.1. The problem does not occur with gcc 3.4.1, 3.4.4, Borland 5.5, and Visual Studio 7 and 8. The problem I am seeing is that gcc 4.x is unable to resolve which template function should be used in certain contexts. I have tried to reduce the code down to a small example that is included below. The problem boils down to one template function calling another, as yet undefined template function, and then not being able to resolve which template function definition should be called. Another factor in this that I don't understand is that moving a class that is used as a parameter to the function template out of a namespace eliminates the issue. In the example below, there are two template classes, Good_data and Bad_data, with the only difference being that Bad_data is declared within a namespace. There are also two template functions, early_function() and late_function(), with the only difference being when they are defined relative to the template functions they invoke. >From the compiler output, early_function() fails to compile when used with Bad_data, but is OK when used with Good_data. This is what drives me to the conclusion that the compiler is not using template function definitions that follow their usage. I have no idea why the namespace makes a difference. Here is the code example followed by the compile info: #include <iostream> template <typename T> class Good_data { // Lack of namespace allows this to work public: Good_data() :val() {} T get() const { return val; } private: T val; }; namespace A { // Namespace injection causes failure template <typename T> class Bad_data { public: Bad_data() :val() {} T get() const { return val; } private: T val; }; } // Forward declaration of template function. template <typename T> inline void display(const T& value); // Problem shows up in this template function which // uses display() prior to it being defined. template <typename T> void early_function(const T& value) { display(value); } // Default template function implementation template <typename T> inline void display(const T& value) { std::cout << value << std::endl; } // Template function specialization for Good_data. template <typename T> inline void display(const Good_data<T>& value) { display(value.get()); } // Template function specialization for Bad_data. template <typename T> inline void display(const A::Bad_data<T>& value) { display(value.get()); } // This function works apparently because specializations // are defined prior to its definition. template <typename T> void late_function(const T& value) { display(value); } int main(int, const char* const) { Good_data<int> good; A::Bad_data<int> bad; early_function(good); // OK early_function(bad); // Compilation error here with gcc 4.x!!! late_function(good); // OK late_function(bad); // OK return 0; } Here is the compilation information: Using built-in specs. Target: i586-suse-linux Configured with: ../configure --enable-threads=posix --prefix=/usr --with-local-prefix=/usr/local --infodir=/usr/share/info --mandir=/usr/share/man --libdir=/usr/lib --libexecdir=/usr/lib --enable-languages=c,c++,objc,fortran,obj-c++,java,ada --enable-checking=release --with-gxx-include-dir=/usr/include/c++/4.1.2 --enable-ssp --disable-libssp --disable-libgcj --with-slibdir=/lib --with-system-zlib --enable-shared --enable-__cxa_atexit --enable-libstdcxx-allocator=new --program-suffix= --enable-version-specific-runtime-libs --without-system-libunwind --with-cpu=generic --host=i586-suse-linux Thread model: posix gcc version 4.1.2 20070115 (prerelease) (SUSE Linux) gcc --save-temps -c -g -Werror -W -Wall ../../../application/example/example.cpp ../../../application/example/example.cpp: In function âvoid display(const T&) [with T = A::Bad_data<int>]â: ../../../application/example/example.cpp:33: instantiated from âvoid early_function(const T&) [with T = A::Bad_data<int>]â ../../../application/example/example.cpp:66: instantiated from here ../../../application/example/example.cpp:39: error: no match for âoperator<<â in âstd::cout << valueâ /usr/include/c++/4.1.2/bits/ostream.tcc:67: note: candidates are: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>& (*)(std::basic_ostream<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.1.2/bits/ostream.tcc:78: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ios<_CharT, _Traits>& (*)(std::basic_ios<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.1.2/bits/ostream.tcc:90: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::ios_base& (*)(std::ios_base&)) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.1.2/bits/ostream.tcc:241: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.1.2/bits/ostream.tcc:264: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long unsigned int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.1.2/bits/ostream.tcc:102: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(bool) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.1.2/bits/ostream.tcc:125: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.1.2/bits/ostream.tcc:157: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short unsigned int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.1.2/bits/ostream.tcc:183: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.1.2/bits/ostream.tcc:215: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(unsigned int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.1.2/bits/ostream.tcc:288: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long long int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.1.2/bits/ostream.tcc:311: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long long unsigned int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.1.2/bits/ostream.tcc:361: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(double) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.1.2/bits/ostream.tcc:335: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(float) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.1.2/bits/ostream.tcc:384: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long double) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.1.2/bits/ostream.tcc:407: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(const void*) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.1.2/bits/ostream.tcc:430: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_streambuf<_CharT, _Traits>*) [with _CharT = char, _Traits = std::char_traits<char>] -- Summary: Template function resolution failure Product: gcc Version: 4.1.2 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: mpeuser at sandel dot com http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33951