[gnu.g++.bug] Stream Manipulators

ned@pebbles.cad.mcc.com (Ned Nowotny) (02/16/90)

In article <RICH.90Feb10131724@kalliope.Rice.edu> rich@Rice.edu (Rich Murphey) writes:
=>Desmond D'Souza asks about stream manipulators:
=>>
=>>   According to the AT&T C++ 2.0 Library Manual (p 3-18) the following
=>>   should be sufficient to define a simple manipulator called "tab". SUN C++
=>>   accepts it, g++ 1.36.4 wont compile it, complaining it "cannot resolve
=>>   overloaded function `tab' based on non-function type". 
=>>
=>>   //--------------------- begin -------------
=>>   #include<stream.h>
=>>
=>>   ostream& tab(ostream& o) {
=>>   return o << "\t"; }
>>
=>>   main () {
=>>   cout << 1 << tab << 2 << tab << 3 ;
=>>   }
=>>   //--------------------- end -------------
=>>
=>Perhaps this is naive, but the definition of tab as a function and
=>it's use as a variable are confusing.
=>
=>It seems like you want to create an object which prints a tab when
=>output to a stream.  One solutiong to your problem in g++ might be:
=>
=>#include <stream.h>
=>class Tab
=>{
=>public:
=>  friend ostream& operator << (ostream&, const Tab&);
=>};
=>inline friend ostream& operator << (ostream& out, const Tab& p)
=>{
=>  return out << "\t";
=>}
=>Tab tab;
=>
=>main ()
=>{
=>  cout << 1 << tab << 2 << tab << 3 ;
=>}
=>

As Desmond has already reported, there is a problem with the way G++ wants to
handle IO manipulators.  While Rich has a solution which does work, it is more
of a work around for the current problem than it is a desirable implementation.

A reasonable (IMHO) implementation is as follows:

-----  Begin iomanip.h -----

#include <stream.h>

/* Consider this free of copyright if you wish to use it.  It was   */
/* independently developed.  (I.e. I didn't look at anyone's source */
/* to come up with this.  Of course, that may be obvious.)          */

// IO Manipulators

inline ostream& operator<<( ostream& ostrm, ostream& (*func_ptr)( ostream& ) )
{
    return func_ptr( ostrm );
}

inline ostream& tab( ostream& ostrm )
{
    return ostrm << "\t";
}

inline ostream& nl( ostream& ostrm )
{
    return ostrm << "\n";
}

inline ostream& flush( ostream& ostrm )
{
    ostrm.flush();
    return ostrm;
}

inline ostream& endl( ostream& ostrm )
{
    return ostrm << nl << flush;
}

----- End iomanip.h -----

----- Begin main.c -----
#include <iomanip.h>

main()
{
    cout << tab << "Hello, world!!!" << endl;
}

----- End main.c -----

When compiled with G++ 1.36.4, this code generates the following complaints:

./iomanip.h: In function class ostream &endl (class ostream &):
In file included from main.c:1:
./iomanip.h:33: cannot resolve overloaded function `nl' based on non-function type
./iomanip.h:33: type conversion required for type `ostream'
main.c: In function int main ():
main.c:5: cannot resolve overloaded function `tab' based on non-function type
main.c:5: type conversion required for type `ostream'

Now, I may just not be able to understand what G++ is trying to tell me, but
the code listed above seems reasonable to me and the complaints I get from
G++ don't seem to be valid.  In particular, nothing included by the libg++
stream.h file included in iomanip.h above should in any way cause either nl
or tab to be overloaded.

Ned Nowotny, MCC CAD Program, Box 200195, Austin, TX  78720  Ph: (512) 338-3715
ARPA: ned@mcc.com                   UUCP: ...!cs.utexas.edu!milano!cadillac!ned
-------------------------------------------------------------------------------
"We have ways to make you scream." - Intel advertisement in the June 1989 DDJ.