rick@ADS.COM (Rick Chestek) (02/06/90)
I have a code fragment which executes differently on a Sun 4 and a Sun 3. The Sun 3 version executes as intended; the Sun 4 version does not. The code has a method, make_child, which I invoke three different ways in this fragment. On a Sun 4, the third technique returns a different answer from the first two. On the Sun 3, all 3 techniques return the same value. The technique that fails is the case where the method is called via a pointer. When the technique fails, the returned value is the value of address of the object, i.e. "this" (although my code fragment doesn't print this to demonstrate it). Also, to be honest, I'm not sure that the compilation of this code is really correct in either case; I appear unable to treat the ptr in the same manner as a function name as my copy of Lippmann indicates; i.e. in the code below you will find the line: (*m_c_ptr)(); My reading of Lippman indicates that I should be able to use: m_c_ptr(); but this results in compile time errors. I have also had troubles using the pointer from outside the class (i.e. I haven't been able to get anything like (parent->*m_child_ptr)() through the compiler) so I created the make_child2 method. I don't believe that this should be necessary. Here is the source, as produced by the command "g++ -E": ----------------------------------------------------------------------------- # 1 "test.C" # 1 "/usr/local/gnu/lib/g++-include/stream.h" 1 #pragma once # 1 "/usr/local/gnu/lib/g++-include/File.h" 1 #pragma once # 1 "/usr/local/gnu/lib/g++-include/builtin.h" 1 #pragma once typedef void (*one_arg_error_handler_t)(const char*); typedef void (*two_arg_error_handler_t)(const char*, const char*); # 1 "/usr/local/gnu/lib/g++-include/stddef.h" 1 #pragma once typedef unsigned long size_t; typedef long int ptrdiff_t; typedef unsigned char wchar_t; # 40 "/usr/local/gnu/lib/g++-include/builtin.h" 2 # 1 "/usr/local/gnu/lib/g++-include/std.h" 1 #pragma once # 1 "/usr/local/gnu/lib/g++-include/stdio.h" 1 #pragma once # 79 "/usr/local/gnu/lib/g++-include/stdio.h" # 114 "/usr/local/gnu/lib/g++-include/stdio.h" # 156 "/usr/local/gnu/lib/g++-include/stdio.h" extern struct _iobuf { int _cnt; char* _ptr; char* _base; int _bufsiz; short _flag; char _file; } _iob[]; typedef struct _iobuf FILE; # 193 "/usr/local/gnu/lib/g++-include/stdio.h" extern "C" { int _doprnt(const char*, void*, FILE*); int _doscan(FILE*, const char*, ...); int _filbuf(FILE*); int _flsbuf(unsigned, FILE*); int fclose(FILE*); FILE* fdopen(int, const char*); int fflush(FILE*); int fgetc(FILE*); char* fgets(char*, int, FILE *); FILE* fopen(const char*, const char*); int fprintf(FILE*, const char* ...); int fputc(int, FILE*); int fputs(const char*, FILE*); int fread(void*, int, int, FILE*); FILE* freopen(const char*, const char*, FILE*); int fscanf(FILE*, const char* ...); int fseek(FILE*, long, int); long ftell(FILE *); int fwrite(const void*, int, int, FILE*); char* gets(char*); int getw(FILE*); int pclose(FILE*); FILE* popen(const char*, const char*); int printf(const char* ...); int puts(const char*); int putw(int, FILE*); int rewind(FILE*); int scanf(const char* ...); int setbuf(FILE*, char*); int setbuffer(FILE*, char*, int); int setlinebuf(FILE*); int setvbuf(FILE*, char*, int, int); int sscanf(char*, const char* ...); FILE* tmpfile(); int ungetc(int, FILE*); int vfprintf(FILE*, const char*, ...); int vprintf(const char*, ... ); char* sprintf(char*, const char* ...); char* vsprintf(char*, const char*, ...); } # 30 "/usr/local/gnu/lib/g++-include/std.h" 2 extern "C" { void volatile _exit(int); void volatile abort(void); int abs(int); int access(const char*, int); int acct(const char*); unsigned alarm(unsigned); double atof(const char*); int atoi(const char*); long atol(const char*); int bind(int, void*, int); int brk(void*); int bsearch (const void *, const void *, unsigned long, unsigned long, auto int (*ptf)(const void*, const void*)); void* calloc(unsigned, unsigned); void cfree(void*); int chdir(const char*); int chmod(const char*, int); int chown(const char*, int, int); long clock(void); int close(int); int creat(const char*, unsigned long int); char* crypt(const char*, const char*); char* ctermid(char*); char* cuserid(char*); double drand48(void); int dup(int); int dup2(int, int); int dysize(int); char* ecvt(double, int, int*, int*); char* encrypt(char*, int); double erand(short*); int execl(const char*, const char *, ...); int execle(const char*, const char *, ...); int execlp(const char*, const char*, ...); int exect(const char*, const char**, char**); int execv(const char*, const char**); int execve(const char*, const char**, char**); int execvp(const char*, const char**); void volatile exit(int); int fchmod(int, int); int fchown(int, int, int); int fcntl(int, int, ...); char* fcvt(double, int, int*, int*); int ffs(int); int flock(int, int); int fork(void); void free(void*); int fsync(int); long ftok(const char*, int); int ftruncate(int, unsigned long); char* gcvt(double, int, char*); char* getcwd(char*, int); int getdomainname(char*, int); int getdtablesize(void); int getegid(void); char* getenv(const char*); int geteuid(void); int getgid(void); int getgroups(int, int*); long gethostid(void); int gethostname(char*, int); char* getlogin(void); int getopt(int, const char**, const char*); int getpagesize(void); char* getpass(const char*); int getpgrp(void); int getpid(void); int getppid(void); int getpriority(int, int); int getpw(int, char*); unsigned getuid(void); char* getwd(char*); char* initstate(unsigned, char*, int); int ioctl(int, int, char*); int isatty(int); long jrand48(short*); int kill(int, int); int killpg(int, int); void lcong48(short*); int link(const char*, const char*); int listen(int, int); int lock(int, int, long); long lrand48(void); long lseek(int, long, int); void* malloc(unsigned); unsigned malloc_usable_size(void*); void* memalign(unsigned, unsigned); void* memccpy(void*, const void*, int, int); void* memchr(const void*, int, int); int memcmp(const void*, const void*, int); void* memcpy(void*, const void*, int); void* memset(void*, int, int); int mkdir(const char*, int); int mknod(const char*, int, int); int mkstemp(char*); char* mktemp(char*); long mrand48(void); int nice(int); long nrand48(short*); int open(const char*, int, ...); void volatile pause(void); void perror(const char*); int pipe(int*); int profil(char*, int, int, int); int psignal(unsigned, char*); int ptrace(int, int, int, int); int putenv(const char*); int qsort(void*, int, unsigned, auto (*ptf)(void*,void*)); int rand(void); long random(void); int read(int, void*, unsigned); int readlink(const char*, char*, int); void* realloc(void*, unsigned); int rename(const char*, const char*); int rmdir(const char*); void* sbrk(int); short* seed48(short*); int send(int, char*, int, int); int setgid(int); int sethostname(char*, int); int setkey(const char*); int setpgrp(int, int); int setpriority(int, int, int); int setregid(int, int); int setreuid(int, int); char* setstate(char*); int setuid(int); int sigblock(int); int siginterrupt(int, int); int sigpause(int); int sigsetmask(int); unsigned sleep(unsigned); int socket(int, int, int); int srand(int); void srand48(long); void srandom(int); int stime(long*); char* strcat(char*, const char*); char* strchr(const char*, int); int strcmp(const char*, const char*); char* strcpy(char*, const char*); int strcspn(const char*, const char*); char* strdup(const char*); int strlen(const char*); char* strncat(char*, const char*, int); int strncmp(const char*, const char*, int); char* strncpy(char*, const char*, int); char* strpbrk(const char*, const char*); char* strrchr(const char*, int); int strspn(const char*, const char*); double strtod(const char*, char**); char* strtok(char*, const char*); long strtol(const char*, char**, int); void swab(void*, void*, int); int symlink(const char*, const char*); int syscall(int, ...); int system(const char*); char* tempnam(char*, char*); int tgetent(char*, char*); int tgetnum(char*); int tgetflag(char*); char* tgetstr(char *, char **); char* tgoto(char*, int, int); long time(long*); char* tmpnam(char*); int tputs(char *, int, auto int (*)()); int truncate(const char*, unsigned long); char* ttyname(int); int ttyslot(void); unsigned ualarm(unsigned, unsigned); long ulimit(int, long); int umask(int); int unlink(const char*); unsigned usleep(unsigned); int vadvise(int); void* valloc(unsigned); int vfork(void); int vhangup(void); int wait(int*); int write(int, const void*, unsigned); } extern "C" { int bcmp(const void*, const void*, int); void bcopy(const void*, void*, int); void bzero(void*, int); char* index(const char*, int); char* rindex(const char*, int); } extern char** environ; extern volatile int errno; extern char* sys_errlist[]; extern int sys_nerr; extern char* optarg; extern int opterr; extern int optind; extern "C" void* alloca(unsigned long); # 41 "/usr/local/gnu/lib/g++-include/builtin.h" 2 # 1 "/usr/local/gnu/lib/g++-include/math.h" 1 #pragma once # 64 "/usr/local/gnu/lib/g++-include/math.h" extern "C" { double acos(double); double acosh(double); double asin(double); double asinh(double); double atan(double); double atan2(double, double); double atanh(double); double cbrt(double); double ceil(double); double copysign(double,double); double cos(double); double cosh(double); double drem(double,double); double erf(double); double erfc(double); double exp(double); double expm1(double); double fabs(double); double finite(double); double floor(double); double frexp(double, int*); double gamma(double); double hypot(double,double); double infnan(int); int isinf(double); int isnan(double); double j0(double); double j1(double); double jn(int, double); double ldexp(double, int); double lgamma(double); double log(double); double log10(double); double log1p(double); double logb(double); double modf(double, double*); double pow(double, double); double rint(double); double scalb(double, int); double sin(double); double sinh(double); double sqrt(double); double tan(double); double tanh(double); double y0(double); double y1(double); double yn(int, double); double aint(double); double anint(double); int irint(double); int nint(double); } struct libm_exception { int type; char* name; double arg1, arg2, retval; }; extern "C" int matherr(libm_exception*); # 1 "/usr/local/gnu/lib/g++-include/values.h" 1 #pragma once # 161 "/usr/local/gnu/lib/g++-include/values.h" # 148 "/usr/local/gnu/lib/g++-include/math.h" 2 # 42 "/usr/local/gnu/lib/g++-include/builtin.h" 2 long gcd(long, long); long lg(unsigned long); double pow(double, long); long pow(long, long); double start_timer(); double return_elapsed_time(double last_time = 0.0); char* itoa(long x, int base = 10, int width = 0); char* itoa(unsigned long x, int base = 10, int width = 0); char* itoa(long long x, int base = 10, int width = 0); char* itoa(unsigned long long x, int base = 10, int width = 0); char* dtoa(double x, char cvt = 'g', int width = 0, int prec = 6); char* hex(long x, int width = 0); char* hex(unsigned long x, int width = 0); char* oct(long x, int width = 0); char* oct(unsigned long x, int width = 0); char* dec(long x, int width = 0); char* dec(unsigned long x, int width = 0); char* form(const char* fmt ...); char* chr(char ch, int width = 0); char* str(const char* s, int width = 0); unsigned int hashpjw(const char*); unsigned int multiplicativehash(int); unsigned int foldhash(double); extern void default_one_arg_error_handler(const char*); extern void default_two_arg_error_handler(const char*, const char*); extern two_arg_error_handler_t lib_error_handler; extern two_arg_error_handler_t set_lib_error_handler(two_arg_error_handler_t f); static inline double abs(double arg) { return (arg < 0.0)? -arg : arg; } static inline float abs(float arg) { return (arg < 0.0)? -arg : arg; } static inline short abs(short arg) { return (arg < 0)? -arg : arg; } static inline long abs(long arg) { return (arg < 0)? -arg : arg; } static inline int sign(long arg) { return (arg == 0) ? 0 : ( (arg > 0) ? 1 : -1 ); } static inline int sign(double arg) { return (arg == 0.0) ? 0 : ( (arg > 0.0) ? 1 : -1 ); } static inline long sqr(long arg) { return arg * arg; } static inline double sqr(double arg) { return arg * arg; } static inline int even(long arg) { return !(arg & 1); } static inline int odd(long arg) { return (arg & 1); } static inline long lcm(long x, long y) { return x / gcd(x, y) * y; } static inline void setbit(long& x, long b) { x |= (1 << b); } static inline void clearbit(long& x, long b) { x &= ~(1 << b); } static inline int testbit(long x, long b) { return ((x & (1 << b)) != 0); } # 28 "/usr/local/gnu/lib/g++-include/File.h" 2 enum io_mode { io_readonly = 0, io_writeonly = 1, io_readwrite = 2, io_appendonly = 3, io_append = 4, }; enum access_mode { a_createonly = 0, a_create = 1, a_useonly = 2, a_use = 3, }; enum state_value { _good = 0, _eof = 1, _fail = 2, _bad = 4 }; class Filebuf; class File { friend class Filebuf; protected: FILE* fp; char* nm; char rw; state_value state; long stat; void initialize(); void reinitialize(const char*); char *readline (int chunk_number, char terminator); public: File(); File(const char* filename, io_mode m, access_mode a); File(const char* filename, const char* m); File(int filedesc, io_mode m); File(FILE* fileptr); File(int sz, char* buf, io_mode m); ~File(); File& open(const char* filename, io_mode m, access_mode a); File& open(const char* filename, const char* m); File& open(int filedesc, io_mode m); File& open(FILE* fileptr); File& close(); File& remove(); int filedesc(); const char* name(); void setname(const char* newname); int iocount(); int rdstate(); int eof(); int fail(); int bad(); int good(); int readable(); int writable(); int is_open(); operator void*(); void error(); void clear(state_value f = _good); void set(state_value f); void unset(state_value f); File& failif(int cond); void check_state(); File& get(char& c); File& put(char c); File& unget(char c); File& putback(char c); File& put(const char* s); File& get (char* s, int n, char terminator = '\n'); File& getline(char* s, int n, char terminator = '\n'); File& gets (char **s, char terminator = '\n'); File& read(void* x, int sz, int n); File& write(void* x, int sz, int n); File& form(const char* ...); File& scan(const char* ...); File& flush(); File& flush(char ch); int fill(); File& seek(long pos, int seek_mode=0); long tell(); File& setbuf(int buffer_kind); File& setbuf(int size, char* buf); File& raw(); }; extern void verbose_File_error_handler(char*); extern void quiet_File_error_handler(char*); extern void fatal_File_error_handler(char*); extern one_arg_error_handler_t File_error_handler; extern one_arg_error_handler_t set_File_error_handler(one_arg_error_handler_t); inline int File::filedesc() { return ((fp)->_file) ; } inline const char* File::name() { return nm; } inline int File::iocount() { return stat; } inline void File::clear(state_value flag) { state = flag; } inline void File::set(state_value flag) { state = state_value(int(state) | int(flag)); } inline void File::unset(state_value flag) { state = state_value(int(state) & ~int(flag)); } inline int File::readable() { if (fp != 0) { if ( (((fp)->_flag& 00020 )!=0) ) set(_eof); if ( (((fp)->_flag& 00040 )!=0) ) set(_bad);} return (state == _good && (rw & 01)); } inline int File::writable() { if (fp != 0 && (((fp)->_flag& 00040 )!=0) ) set(_bad); return ((int(state) & (int(_fail)|int(_bad))) == 0 && (rw & 02)); } inline int File::is_open() { return (fp != 0); } inline File& File::raw() { return this->File::setbuf( 00004 ); } inline void File::check_state() { if (fp != 0) { if ( (((fp)->_flag& 00020 )!=0) ) set(_eof); else unset(_eof); if ( (((fp)->_flag& 00040 )!=0) ) set(_bad); } } inline File& File::failif(int cond) { if (cond) set(_fail); return *this; } inline File& File::get(char& c) { if (readable()) { int ch = (--(fp)->_cnt>=0?(int)(*(unsigned char*)(fp)->_ptr++):_filbuf(fp)) ; c = ch; failif (ch == (-1) ); } return *this; } inline File& File::put(char c) { return failif (!writable() || (--( fp)->_cnt>=0? ((int)((unsigned char)((*( fp)->_ptr++=(unsigned)(c))))):_flsbuf((unsigned)(c), fp)) == (-1) ); } inline File& File::unget(char c) { return failif(!is_open() || !(rw & 01) || ungetc(c, fp) == (-1) ); } inline File& File::putback(char c) { return failif (!is_open() || !(rw & 01) || ungetc(c, fp) == (-1) ); } inline File& File::read(void* x, int sz, int n) { return failif (!readable() || (stat = fread(x, sz, n, fp)) != n); } inline File& File::write(void* x, int sz, int n) { return failif (!writable() || (stat = fwrite(x, sz, n, fp)) != n); } inline File& File::flush() { return failif(!is_open() || fflush(fp) == (-1) ); } inline File& File::flush(char ch) { return failif(!is_open() || _flsbuf(ch, fp) == (-1) ); } inline int File::fill() { failif(!is_open() || (stat = _filbuf(fp)) == (-1) ); return stat; } inline File& File::seek(long pos, int seek_mode) { return failif (!is_open() || fseek(fp, pos, seek_mode) < 0); } inline long File::tell() { failif (!is_open() || ((stat = ftell(fp)) < 0)); return stat; } inline int File::rdstate() { check_state(); return state; } inline File::operator void*() { check_state(); return (int(state) & (int(_bad)|int(_fail)))? 0 : this ; } inline int File::eof() { check_state(); return state & _eof; } inline int File::fail() { check_state(); return state & _fail; } inline int File::bad() { check_state(); return state & _bad; } inline int File::good() { check_state(); return rdstate() == _good; } # 34 "/usr/local/gnu/lib/g++-include/stream.h" 2 # 1 "/usr/local/gnu/lib/g++-include/streambuf.h" 1 #pragma once enum open_mode { input=0, output=1, append=2 }; class streambuf { public: char* base; char* pptr; char* gptr; char* eptr; char alloc; streambuf(); streambuf(char* buf, int buflen); virtual ~streambuf(); int doallocate(); int allocate(); int must_overflow(int ch); virtual int overflow(int c = (-1) ); virtual int underflow(); int sgetc(); int snextc(); void stossc(); int sputback(char); int sputc(int c = (-1) ); virtual streambuf* setbuf(char* buf, int buflen, int preloaded_count = 0); int sputs(const char* s); int sputsn(const char* s, int len); virtual const char* name(); virtual streambuf* open(const char* name, open_mode m); virtual streambuf* open(const char* filename, io_mode m, access_mode a); virtual streambuf* open(const char* filename, const char* m); virtual streambuf* open(int filedesc, io_mode m); virtual streambuf* open(FILE* fileptr); virtual int is_open(); virtual int close(); virtual void error(); }; class filebuf: public streambuf { public: int fd; char opened; int overflow(int c = (-1) ); int underflow(); filebuf(); filebuf(int newfd); filebuf(int newfd, char* buf, int buflen); ~filebuf(); streambuf* open(const char* name, open_mode m); int is_open(); int close(); }; class Filebuf: public streambuf { public: File* Fp; void init_streambuf_ptrs(); int overflow(int c = (-1) ); int underflow(); Filebuf(); Filebuf(const char* filename, io_mode m, access_mode a); Filebuf(const char* filename, const char* m); Filebuf(int filedesc, io_mode m); Filebuf(FILE* fileptr); ~Filebuf(); const char* name(); streambuf* setbuf(char* buf, int buflen, int preloaded_count = 0); streambuf* open(const char* filename, io_mode m, access_mode a); streambuf* open(const char* filename, const char* m); streambuf* open(int filedesc, io_mode m); streambuf* open(FILE* fileptr); int is_open(); int close(); void error(); }; inline int streambuf::must_overflow(int ch) { return pptr >= eptr || ch == '\n'; } inline int streambuf::allocate() { return (base == 0)? doallocate() : 0; } inline int streambuf::sgetc() { return (gptr >= pptr)? underflow() : int(*gptr); } inline int streambuf::snextc() { ++gptr; return (gptr >= pptr)? underflow() : int(*gptr); } inline void streambuf::stossc() { if (gptr >= pptr) underflow(); else gptr++; } inline int streambuf::sputback(char ch) { return (gptr > base)? (*--gptr = ch) : (-1) ; } inline int streambuf::sputc(int ch) { return must_overflow(ch)? overflow(ch) : (*pptr++ = char(ch)); } # 35 "/usr/local/gnu/lib/g++-include/stream.h" 2 class whitespace { char filler; }; class istream; class ostream { friend class istream; protected: streambuf* bp; state_value state; char ownbuf; public: ostream(const char* filename, io_mode m, access_mode a); ostream(const char* filename, const char* m); ostream(int filedesc, io_mode m); ostream(FILE* fileptr); ostream(int sz, char* buf); ostream(int filedesc, char* buf, int buflen); ostream(int filedesc); ostream(streambuf* s); ~ostream(); ostream& open(const char* filename, io_mode m, access_mode a); ostream& open(const char* filename, const char* m); ostream& open(int filedesc, io_mode m); ostream& open(FILE* fileptr); ostream& open(const char* filenam, open_mode m); ostream& close(); ostream& flush(); int rdstate(); int eof(); int fail(); int bad(); int good(); int readable(); int writable(); int is_open(); operator void*(); int operator !(); const char* name(); char* bufptr(); void error(); void clear(state_value f = _good); void set(state_value f); void unset(state_value); ostream& failif(int cond); ostream& put(char c); ostream& put(const char* s); ostream& put(const char* s, int slen); ostream& form(const char* fmt, ...); ostream& operator << (short n); ostream& operator << (unsigned short n); ostream& operator << (int n); ostream& operator << (unsigned int n); ostream& operator << (long n); ostream& operator << (unsigned long n); ostream& operator << (long long n); ostream& operator << (unsigned long long n); ostream& operator << (float n); ostream& operator << (double n); ostream& operator << (const char* s); ostream& operator << (char c); }; class istream { friend void eatwhite(istream& s); protected: streambuf* bp; state_value state; ostream* tied_to; char skipws; char ownbuf; void _flush(); char* readline (int chunk_number, char terminator); public: istream(const char* filename, io_mode m, access_mode a, int sk=1, ostream* t = 0); istream(const char* filename, const char* m, int sk=1, ostream* t = 0); istream(int filedesc, io_mode m, int sk=1, ostream* t = 0); istream(FILE* fileptr, int sk=1, ostream* t = 0); istream(int sz, char* buf, int sk=1, ostream* t = 0); istream(int filedesc, int sk=1, ostream* t = 0); istream(int filedesc, char* buf, int buflen, int sk=1, ostream* t = 0); istream(streambuf* s, int sk=1, ostream* t = 0); ~istream(); istream& open(const char* filename, io_mode m, access_mode a); istream& open(const char* filename, const char* m); istream& open(int filedesc, io_mode m); istream& open(FILE* fileptr); istream& open(const char* filenam, open_mode m); istream& close(); ostream* tie(ostream* s); int skip(int); int rdstate(); int eof(); int fail(); int bad(); int good(); int readable(); int writable(); int is_open(); operator void*(); int operator !(); const char* name(); char* bufptr(); void error(); void clear(state_value f = _good); void set(state_value f); void unset(state_value f); istream& failif(int cond); istream& get(char& c); istream& unget(char c); istream& putback(char c); istream& get (char* s, int n, char terminator = '\n'); istream& getline(char* s, int n, char terminator = '\n'); istream& gets (char **s, char terminator = '\n'); istream& operator >> (char& c); istream& operator >> (short& n); istream& operator >> (unsigned short& n); istream& operator >> (int& n); istream& operator >> (unsigned int& n); istream& operator >> (long& n); istream& operator >> (unsigned long& n); istream& operator >> (long long& n); istream& operator >> (unsigned long long& n); istream& operator >> (float& n); istream& operator >> (double& n); istream& operator >> (char* s); istream& operator >> (whitespace& w); }; extern istream cin; extern ostream cout; extern ostream cerr; extern whitespace WS; inline void ostream::clear(state_value flag) { state = flag; } inline void ostream::set(state_value flag) { state = state_value(int(state) | int(flag)); } inline void ostream::unset(state_value flag) { state = state_value(int(state) & ~int(flag)); } inline int ostream::rdstate() { return int(state); } inline int ostream::good() { return state == _good; } inline int ostream::eof() { return int(state) & int(_eof); } inline int ostream::fail() { return int(state) & int(_fail); } inline int ostream::bad() { return int(state) & int(_bad); } inline ostream::operator void*() { return (state == _good)? this : 0; } inline int ostream::operator !() { return (state != _good); } inline ostream& ostream::failif(int cond) { if (cond) set(_fail); return *this; } inline int ostream::is_open() { return bp->is_open(); } inline int ostream::readable() { return 0; } inline int ostream::writable() { return (bp != 0) && (state == _good); } inline char* ostream::bufptr() { return bp->base; } inline ostream& ostream::flush() { bp->overflow(); return *this; } inline ostream& ostream::close() { bp->overflow(); bp->close(); return *this; } inline ostream& ostream::put(char ch) { return failif((state != _good) || bp->sputc(ch) == (-1) ); } inline ostream& ostream::operator << (char ch) { return failif((state != _good) || bp->sputc(ch) == (-1) ); } inline ostream& ostream::put(const char* s) { return failif((state != _good) || bp->sputs(s) == (-1) ); } inline ostream& ostream::put(const char* s, int len) { return failif((state != _good) || bp->sputsn(s, len) == (-1) ); } inline ostream& ostream::operator << (const char* s) { return failif((state != _good) || bp->sputs(s) == (-1) ); } inline void istream::clear(state_value flag) { state = flag; } inline void istream::set(state_value flag) { state = state_value(int(state) | int(flag)); } inline void istream::unset(state_value flag) { state = state_value(int(state) & ~int(flag)); } inline int istream::rdstate() { return int(state); } inline int istream::good() { return state == _good; } inline int istream::eof() { return int(state) & int(_eof); } inline int istream::fail() { return int(state) & int(_fail); } inline int istream::bad() { return int(state) & int(_bad); } inline istream::operator void*() { return (state == _good)? this : 0; } inline int istream::operator !() { return (state != _good); } inline istream& istream::failif(int cond) { if (cond) set(_fail); return *this; } inline int istream::is_open() { return bp->is_open(); } inline int istream::readable() { return (bp != 0) && (bp->is_open()) && (state == _good); } inline int istream::writable() { return 0; } inline void istream::_flush() { if(tied_to != 0) tied_to->flush(); } inline char* istream::bufptr() { return bp->base; } inline istream& istream::close() { bp->close(); return *this; } inline int istream::skip(int sk) { int was = skipws; skipws = sk; return was; } inline ostream* istream::tie(ostream* s) { ostream* was = tied_to; tied_to = s; return was; } inline istream& istream::unget(char c) { if (bp->sputback(c) == (-1) ) set(_fail); return *this; } inline istream& istream::putback(char c) { if (bp->sputback(c) == (-1) ) set(_fail); return *this; } inline void eatwhite(istream& s) { s >> WS; } # 1 "test.C" 2 class childptr; typedef childptr* (childptr::*make_child_ptr)(); class childptr { public: childptr(); childptr* make_child(); childptr* make_child2(); make_child_ptr m_c_ptr; }; childptr* childptr::make_child() { childptr* newchild; newchild = new childptr; cout << "childptr::make_child returning " << (int)newchild << "\n"; return (newchild); } childptr* childptr::make_child2() { (*m_c_ptr)(); } childptr::childptr() { m_c_ptr = make_child; } main() { childptr parent; childptr* parent2; childptr* child; child = parent.make_child(); cout << "parent.make_child yielded: " << (int)child << "\n\n"; parent2 = new childptr; child = parent2->make_child(); cout << "parent->make_child() yielded: " << (int)child << "\n\n"; child = parent2->make_child2(); cout << "parent->make_child2() yielded: " << (int)child << "\n\n"; }
tiemann@arkesden.eng.sun.com (Michael Tiemann) (02/12/90)
I have a code fragment which executes differently on a Sun 4 and a Sun 3. The Sun 3 version executes as intended; the Sun 4 version does not. The code has a method, make_child, which I invoke three different ways in this fragment. On a Sun 4, the third technique returns a different answer from the first two. On the Sun 3, all 3 techniques return the same value. The technique that fails is the case where the method is called via a pointer. When the technique fails, the returned value is the value of address of the object, i.e. "this" (although my code fragment doesn't print this to demonstrate it). What you have found is not a bug in GNU C++, but a bug in your program. Since I have seen others bitten before, I am posting it to the net. Had you run GNU C++ with -Wall or -Wreturn-type, the compiler would have found it for you. Also, to be honest, I'm not sure that the compilation of this code is really correct in either case; I appear unable to treat the ptr in the same manner as a function name as my copy of Lippmann indicates; i.e. in the code below you will find the line: (*m_c_ptr)(); My reading of Lippman indicates that I should be able to use: m_c_ptr(); I consider it bad practice to auto-dereference pointer-to-member functions. It is better that people see that they are really pointers. Otherwise, someone unfamiliar with the code could waste time looking for the definition of m_c_ptr as a function. but this results in compile time errors. I have also had troubles using the pointer from outside the class (i.e. I haven't been able to get anything like (parent->*m_child_ptr)() through the compiler) so I created the make_child2 method. I don't believe that this should be necessary. Probably another misunderstanding. If you want to use m_c_ptr in this way, you have to do this: (parent->*(parent->m_c_ptr))() You are not the first to run into this problem. Here is the source, as produced by the command "g++ -E" [edited by MDT]: extern "C" void printf (char *, ...); class childptr; typedef childptr* (childptr::*make_child_ptr)(); class childptr { public: childptr(); childptr* make_child(); childptr* make_child2(); make_child_ptr m_c_ptr; }; childptr* childptr::make_child() { childptr* newchild; newchild = new childptr; printf ("childptr::make_child returning %d\n", (int)newchild); return (newchild); } childptr* childptr::make_child2() { (*m_c_ptr)(); //^^^^^^^^^^^^^ bug: should be return (*m_c_ptr)(); } childptr::childptr() { m_c_ptr = make_child; } main() { childptr parent; childptr* parent2; childptr* child; child = parent.make_child(); printf ("parent.make_child yielded: %d\n\n", (int)child); parent2 = new childptr; child = parent2->make_child(); printf ("parent->make_child() yielded: %d\n\n", (int)child); child = parent2->make_child2(); printf ("parent->make_child2() yielded: %d\n\n", (int)child); }