From: "Bonifati" Newsgroups: comp.os.msdos.djgpp Subject: particular bug in template implementation Date: Tue, 29 Dec 1998 01:14:11 +0100 Organization: Centro Servizi Interbusiness Lines: 214 Message-ID: <7696il$k94$1@fe2.cs.interbusiness.it> NNTP-Posting-Host: 194.243.119.85 X-Newsreader: Microsoft Outlook Express 4.72.3110.5 X-MimeOLE: Produced By Microsoft MimeOLE V4.72.3110.3 To: djgpp AT delorie DOT com DJ-Gateway: from newsgroup comp.os.msdos.djgpp Reply-To: djgpp AT delorie DOT com I have sent this e-mail both to gnu.gcc.bug and bug-g++@prep.ai.mit.edu but nobody answered me. Since this newsgroup always answers me, here it is: (it's an interesting problem and I'm sure there's a bug) I'm an italian student. My name's Antonio Bonifati. I think I have found a bug in your compiler. My computer is a Pentium II 333Mhz. The OS is Windows 98. I have GNU C++ for Win32: C:\C++>g++ -v Reading specs from C:\C++\lib\gcc-lib\i386-mingw32\2.8.1\specs gcc version 2.8.1 Here's a simplified input file that will reproduce the bug: ---------------------------------------------------------------------------- template class Eq { public: const static Eq def; }; template const Eq Eq::def=Eq(); template void F(const Eq& o = Eq::def) { return; } main() { Eq varEq; // line 15 F(varEq); } ---------------------------------------------------------------------------- C:\progs>g++ prova.cpp prova.cpp:15: aggregate `class Eq const Eq::def' has incom plete type and cannot be initialized I think this is a bogus error. Your web page http://www.cygnus.com/misc/g++FAQ_toc.html (G++ FAQ) gave me an idea on how to fix this error (see: Problems with the template implementation). I think problem 1 hasn't been completely eliminated: static data member templates which type is the same of their class are not supported: ---------------------------------------------------------------------------- 1. Static data member templates are not supported in compiler versions older than 2.8.0. You can work around this by explicitly declaring the static variable for each template specialization: template struct A static T t; }; template T A::t = 0; // gets bogus error int A::t = 0; // OK (workaround) ---------------------------------------------------------------------------- This code works: ---------------------------------------------------------------------------- template class Eq { public: const static Eq def; }; // gets bogus error // template // const Eq Eq::def=Eq(); const Eq Eq::def = Eq(); template void F(const Eq& o = Eq::def) { return; } main() { Eq varEq; F(varEq); } ---------------------------------------------------------------------------- This is the original code that has the bug: ---------------------------------------------------------------------------- // File utilita.h #ifndef UTILITAH #define UTILITAH #include #include // generic abs function template inline T abs( const T& a ) { return ( a < 0 ) ? -a : a; } // generic swap function template inline void scambia( T& a1, T& a2 ) { T temp = a1; a1 = a2; a2 = temp; } template class Eq; // generic equality class template class Ord; // generic ordering class // generic minimum function template inline T min( const T& a1, const T& a2, const Ord& o = Ord::def ) { return ( o.precede(a1, a2) ) ? a1 : a2; } // generic maximum function template inline T max( const T& a1, const T& a2, const Ord& o = Ord::def ) { return ( o.precede(a1, a2) ) ? a2 : a1; } template class Eq { public: // signature of an equality function typedef bool (* FUguale) ( const T&, const T& ); // standard equality function which calls '==' virtual bool uguale( const T& a1, const T& a2 ) const { return (fUguale == 0) ? a1 == a2 : fUguale(a1,a2); } // default equality as a static constant const static Eq def; // equality operator for two equalities friend bool operator== ( const Eq& e1, const Eq& e2 ) { return e1.fUguale == e2.fUguale; } Eq( FUguale fug = 0 ) { fUguale = fug; } // costruttore private: // equality function: if 0 operator "==" is used FUguale fUguale; }; template const Eq Eq::def = Eq(); // initialization to the default value // there are two possible ordering directions // DISC is the inverse ordering enum DirOrd { ASC=0, DISC }; template class Ord { public: const DirOrd dirOrd; // ordering direction // signature of an ordering function typedef bool (* FPrecede) ( const T&, const T& ); // comparison operator bool precede( const T& a1, const T& a2 ) const { if ( dirOrd == ASC ) return ( fPrecede == 0 ) ? a1 < a2 : fPrecede (a1,a2); else return ( fPrecede == 0 ) ? a2 < a1 : fPrecede (a2,a1); } // equality operator induced by 'precede' bool uguale( const T& a1, const T& a2 ) const { return !precede (a1,a2) && !precede (a2,a1); } // operator that return the inverse ordering Ord operator! () { return Ord( (dirOrd == ASC) ? DISC : ASC, fPrecede); } // default ordering as a static constant const static Ord def; // equality operator for two orderings friend bool operator== ( const Ord& o1, const Ord& o2 ) { return o1.dirOrd == o2.dirOrd && o1.fPrecede == o2.fPrecede; } // constructor Ord( DirOrd vOrd = ASC, FPrecede fprec = 0 ): dirOrd(vOrd) { fPrecede = fprec; } private: // ordering function: if 0 operator "<" is used FPrecede fPrecede; }; template // initialization to the default value const Ord Ord::def = Ord(); #endif ---------------------------------------------------------------------------- Please answer to abonifati AT telsa DOT it Thank you and happy new year