[comp.lang.c++] Now a bug

wim@targon.UUCP (Wim C. J. van Eerdt) (12/15/87)

Here is another file, that I have got from my colleague:
Gerard van Dorth.
When you want to contact him you can write to:
	Gerard van Dorth
	Nixdorf Computer BV.
	Department: EG4
	Postbus 29
	4130 EA  Vianen
	The Netherlands
Voice: +31 3473 75154
E-mail: No direct contact. (I promise to forward a printed version of your
mail to him.)
Here it goes!

------------------------------------------------------------------------
Subject:  Now a bug (?)

#include <stream.h>


class	string  {

	char	*s;
	int	n;

   public:

	string();
	string( char*   );
	string( string& );

	friend ostream& operator<< ( ostream&, string& );

} ;


// ...


const string	text = "text";

void	call()
{

	cout << text;	// reference to a const object.

}


	A colleague typed the exhibited program and found an error on line
		cout << text;
The message is correct: the 2nd argument of operator<< is a reference to a
string. So he changed the definition into
		friend ostream& operator<< ( ostream&, string );
Surprise, that did not work either: the constructor string( string& ) still
takes the reference of the constant object. Neither skipping the constructor
nor skipping the cont declaration is the answer, who knows the answer.
-- 
	Wim van Eerdt                   E-mail: mcvax!targon!wim
	OSP, Nixdorf Computer Bv, Postbus 29, 4130 EA Vianen
	Nederland. Tel.: +31 3473 62211.

mikem@otc.oz (Mike Mowbray) (12/27/87)

In article <370@targon.UUCP>, Gerard van Dorth says:

> 	A colleague typed the exhibited program and found an error on line
> 		cout << text;

Removing the const declaration of text will work, as will changing the
friend function in class string to:

    friend ostream &operator<<(ostream&, string const &);

 > ...  the constructor string( string& ) still
 > takes the reference of the constant object. Neither skipping the
 > constructor nor skipping the cont declaration is the answer, who knows
 > the answer.

I don't think the problem has anything to do with the ctor. Rather, the
attempt to pass a const string to a function expecting an ordinary one is
what cfront is complaining about. This is correct. Note that if you adopt
the second solution above you'll need to ensure that the operator<<
function doesn't attempt to modify the string, or more errors will then be
produced.


			Mike Mowbray
		    Systems Development
			|||| OTC ||

		    ACSnet:  mikem@otc.oz
		      UUCP:  {uunet,mcvax}!otc.oz!mikem 
		     Phone:  (02) 287-4104
		     Snail:  GPO Box 7000, Sydney 2001, Australia

weh@druhi.ATT.COM (HopkinsBWE) (12/30/87)

In article <370@targon.UUCP>, wim@targon.UUCP (Wim C. J. van Eerdt) writes:
> #include <stream.h>
> 
> class	string  {
> 	//...
>    public:
> 
> 	string();
> 	string( char*   );
> 	string( string& );
> 
> 	friend ostream& operator<< ( ostream&, string& );
> 
> } ;
> 
> const string	text = "text";
> 
> void	call()
> {
> 
> 	cout << text;	// reference to a const object.
> 
> }
> 
> 
> 	A colleague typed the exhibited program and found an error on line
> 		cout << text;
> The message is correct: the 2nd argument of operator<< is a reference to a
> string. So he changed the definition into
> 		friend ostream& operator<< ( ostream&, string );
> Surprise, that did not work either: the constructor string( string& ) still
> takes the reference of the constant object. Neither skipping the constructor
> nor skipping the cont declaration is the answer, who knows the answer.

Cfront won't allow one to pass a constant object by reference into a
function unless the formal argument is also a constant. The error message from
cfront (from a copy of the example in a file named ctest.c) is:

CC  ctest.c:
"ctest.c", line 18: error:  reference to const object
1 error

Line 18 in my file is the ``cout << text; '' line.

Thus, the function should have been declared as:

 	friend ostream& operator<< ( ostream&, const string& );

Sure enough, cfront happily compiled it after the change.

Since changes to parameters passed by reference change the actual
argument, cfront cannot allow a constant to be passed as a non-constant
reference.

The solution of declaring the argument as simply a ``string'' fails
because that requires the creation of a new copy of ``string'' from an
existing string, meaning that string::string(string&) must be called. Since
it declares the argument as a nonconstant reference, it suffers from the
same problem as with operator>> (the same error message from cfront). The
solution is similar: declare the constructor as ``string(const string&);''.
This solution, too, has been confirmed by cfront.

			Bill Hopkins
			AT&T
			ihnp4!druhi!weh