Path: utzoo!attcan!uunet!lll-winken!ncis.llnl.gov!helios.ee.lbl.gov!pasteur!agate!bionet!csd4.milw.wisc.edu!mailrus!tut.cis.ohio-state.edu!rutgers!cmcl2!phri!marob!samperi From: samperi@marob.MASA.COM (Dominick Samperi) Newsgroups: comp.lang.c++ Subject: Re: Fast Fourier Transformer in C++ Summary: Parametrized classes demo & bug Message-ID: <479@marob.MASA.COM> Date: 21 Jan 89 17:59:23 GMT References: <518@cs-spool.calgary.UUCP> <6217@thorin.cs.unc.edu> <6250@thorin.cs.unc.edu> Reply-To: samperi@marob.masa.com (Dominick Samperi) Organization: ESCC New York City Lines: 205 In article <6250@thorin.cs.unc.edu> coggins@coggins.UUCP (Dr. James Coggins) writes: >Seriously, I think we need a LOT more code examples posted to this >newsgroup. Not just demonstrations of errors, but real design >examples. Well, this isn't a real design example, but it addresses an important C++ issue, namely, parametrized classes, implemented via the macro package in . First, it illustrates that there are some rather messy syntactical restrictions (no blanks in the macro formal parameter list, macro expansion inside of comments, etc.), and second, it illustrates that there are some other problems, leading to bugs when the macro package is used (which is the case when BUG is defined). The bug is described in counter::counter(counter& cnt). Any insights would be appreciated. Dominick Samperi samperi@acf8.nyu.edu uunet!hombre!samperi /* #define BUG /* Uncomment this to use and cause a BUG! */ #include #ifdef BUG #include declare(vector,int) ; // NOTE: no spaces allowed between () here! implement(vector,int) ; // NOTE: this macro should only be expanded in ONE file. // ^^^^ can't say the implXXX word here, since // the macro processor doesn't understand //! #else class vector { int *v ; int sz ; public: vector(int) ; vector(vector&) ; ~vector() ; int size() { return sz ; } int& operator[](int) ; vector operator=(vector) ; } ; vector::vector(int siz) { sz = siz ; v = new int[sz] ; } vector::vector(vector& vv) { sz = vv.size() ; v = new int[sz] ; for(int i = 0 ; i < sz ; i++) v[i] = vv[i] ; } vector::~vector() { delete v ; } int& vector::operator[](int i) { return v[i] ; } vector vector::operator=(vector vv) { for(int i = 0 ; i < sz ; i++) v[i] = vv[i] ; return *this ; } #endif class counter { #ifdef BUG vector(int) *low, *high, *incr, *count ; #else vector *low, *high, *incr, *count ; #endif int sz ; public: #ifdef BUG counter(vector(int)&, vector(int)&, vector(int)&) ; #else counter(vector&, vector&, vector&) ; #endif counter(counter&) ; ~counter() ; int size() { return low->size() ; } void reset() { *count = *low ; } void print() ; int operator[](int i) { return (*count)[i] ; } } ; void counter::print() { cerr << "Counter(low,high,incr,count): \n" ; for(int i = 0 ; i < sz ; i++) { cerr << i << ": " << (*low)[i] << " " << (*high)[i] << " " << (*incr)[i] << " " << (*count)[i] << "\n" ; } } #ifdef BUG counter::counter(vector(int)& lo, vector(int)& hi, vector(int)& inc) #else counter::counter(vector& lo, vector& hi, vector& inc) #endif { sz = lo.size() ; #ifdef BUG low = new vector(int)(sz) ; high = new vector(int)(sz) ; incr = new vector(int)(sz) ; count = new vector(int)(sz) ; #else low = new vector(sz) ; high = new vector(sz) ; incr = new vector(sz) ; count = new vector(sz) ; #endif *low = lo ; *high = hi ; *incr = inc ; *count = lo ; } counter::counter(counter& cnt) { cerr << "cnt param before instantiation:\n" ; cnt.print() ; sz = cnt.size() ; #ifdef BUG /* * When BUG is defined, these memory allocation statements cause cnt to be * corrupted, as you will see from the output generated by cnt.print() before * and after this code. */ low = new vector(int)(sz) ; high = new vector(int)(sz) ; incr = new vector(int)(sz) ; count = new vector(int)(sz) ; #else low = new vector(sz) ; high = new vector(sz) ; incr = new vector(sz) ; count = new vector(sz) ; #endif cerr << "cnt after instantiation:\n" ; cnt.print() ; *low = *cnt.low ; *high = *cnt.high ; *incr = *cnt.incr ; *count = *low ; } counter::~counter() { delete count ; delete incr ; delete high ; delete low ; } ostream& operator<<(ostream& s, counter& c) { s << "[ " ; for(int i = 0 ; i < c.size() ; i++) s << form("%2d", c[i]) << " " ; return s << "]\n" ; } main() { #ifdef BUG vector(int) low(3), high(3), incr(3) ; #else vector low(3), high(3), incr(3) ; #endif for(int i = 0 ; i < 3 ; i++) { low[i] = 1 ; high[i] = 5 ; incr[i] = 1 ; } counter select(low, high, incr) ; select.print() ; counter x = select ; }