Mail Archives: djgpp/1998/12/28/19:35:47
From: | "Bonifati" <abonifati AT telsa DOT it>
|
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 T>
class Eq
{ public:
const static Eq def;
};
template<class T>
const Eq<T> Eq<T>::def=Eq<T>();
template<class T>
void F(const Eq<T>& o = Eq<T>::def)
{ return;
}
main()
{ Eq<short> varEq; // line 15
F(varEq);
}
----------------------------------------------------------------------------
C:\progs>g++ prova.cpp
prova.cpp:15: aggregate `class Eq<short int> const Eq<short int>::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 <class T> struct A
static T t;
};
template <class T> T A<T>::t = 0; // gets bogus error
int A<int>::t = 0; // OK (workaround)
----------------------------------------------------------------------------
This code works:
----------------------------------------------------------------------------
template<class T>
class Eq
{ public:
const static Eq def;
};
// gets bogus error
// template<class T>
// const Eq<T> Eq<T>::def=Eq<T>();
const Eq<short> Eq<short>::def = Eq<short>();
template<class T>
void F(const Eq<T>& o = Eq<T>::def)
{ return;
}
main()
{ Eq<short> varEq;
F(varEq);
}
----------------------------------------------------------------------------
This is the original code that has the bug:
----------------------------------------------------------------------------
// File utilita.h
#ifndef UTILITAH
#define UTILITAH
#include <stdlib.h>
#include <string.h>
// generic abs function
template <class T> inline
T abs( const T& a ) { return ( a < 0 ) ? -a : a; }
// generic swap function
template <class T> inline
void scambia( T& a1, T& a2 ) { T temp = a1; a1 = a2; a2 = temp; }
template <class T> class Eq; // generic equality class
template <class T> class Ord; // generic ordering class
// generic minimum function
template <class T> inline
T min( const T& a1, const T& a2, const Ord<T>& o = Ord<T>::def )
{ return ( o.precede(a1, a2) ) ? a1 : a2; }
// generic maximum function
template <class T> inline
T max( const T& a1, const T& a2, const Ord<T>& o = Ord<T>::def )
{ return ( o.precede(a1, a2) ) ? a2 : a1; }
template <class T>
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<T>& e1, const Eq<T>& e2 )
{ return e1.fUguale == e2.fUguale; }
Eq( FUguale fug = 0 ) { fUguale = fug; } // costruttore
private:
// equality function: if 0 operator "==" is used
FUguale fUguale;
};
template <class T>
const Eq<T> Eq<T>::def = Eq<T>(); // initialization to the default value
// there are two possible ordering directions
// DISC is the inverse ordering
enum DirOrd { ASC=0, DISC };
template <class T>
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<T>( (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<T>& o1, const Ord<T>& 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 <class T> // initialization to the default value
const Ord<T> Ord<T>::def = Ord<T>();
#endif
----------------------------------------------------------------------------
Please answer to abonifati AT telsa DOT it
Thank you and happy new year
- Raw text -