www.digitalmars.com Home | Search | C & C++ | D | DMDScript | News Groups | index | prev | next
Archives

D Programming
D
D.gnu
digitalmars.D
digitalmars.D.bugs
digitalmars.D.dtl
digitalmars.D.dwt
digitalmars.D.announce
digitalmars.D.learn
digitalmars.D.debugger

C/C++ Programming
c++
c++.announce
c++.atl
c++.beta
c++.chat
c++.command-line
c++.dos
c++.dos.16-bits
c++.dos.32-bits
c++.idde
c++.mfc
c++.rtl
c++.stl
c++.stl.hp
c++.stl.port
c++.stl.sgi
c++.stlsoft
c++.windows
c++.windows.16-bits
c++.windows.32-bits
c++.wxwindows

digitalmars.empire
digitalmars.DMDScript

c++ - why difference between temp and named variable?

↑ ↓ ← "Steve Strand" <snstrand comcast.net> writes:
This program fails as written, but a fix
is shown in comments:

#include <iostream.h>
#include <strstream.h>

struct mine
{
    int a;
};

ostream& operator << (ostream& out, mine& m)
{
    return out << m.a;
}

istream& operator >> (istream& in, mine& m)
{
    return in >> m.a;
}

int main()
{
    mine mm;

//these two lines work
//  istrstream in("106");
//  if (in >> mm)

//but this one line alternative does not work
    if (istrstream("106") >> mm)

        cout << "mm= " << mm << endl;
    else
        cout << "extract fails" << endl;
}


The bad version gets this error message:
    cannot generate copy constructor for class
    'istream' because of private 'ios'

Why does the compiler need to generate a copy
constructor? The code creates a temporary istrstream,
passes it by reference to operator>>(), then uses the
returned reference to call member function ios::operator
void*(). Neither passing by reference nor calling a
member function involves copy constructing.

Why does the commented-out version work? Giving the
istrstream a name instead of using a temp should not
influence the need for a copy constructor.
Apr 22 2004
↑ ↓ Heinz Saathoff <hsaat bre.ipnet.de> writes:
Hello Steve,

Steve Strand wrote...
 #include <iostream.h>
 #include <strstream.h>
 
 struct mine
 {
     int a;
 };
 
 ostream& operator << (ostream& out, mine& m)
 {
     return out << m.a;
 }
 
 istream& operator >> (istream& in, mine& m)
 {
     return in >> m.a;
 }
 
 int main()
 {
     mine mm;
 
 //these two lines work
 //  istrstream in("106");
 //  if (in >> mm)
 
 //but this one line alternative does not work
     if (istrstream("106") >> mm)

You create a temporary istrstream obj here. Temporarys can only be passed to const references.
 
         cout << "mm= " << mm << endl;
     else
         cout << "extract fails" << endl;
 }

 The bad version gets this error message:
     cannot generate copy constructor for class
     'istream' because of private 'ios'

I think the error message is misleading here. I tried your program with PC-Lint and got this error message: --- Module: stru.cpp if (istrstream("106") >> mm) stru.cpp 28 Info 1776: Converting a string literal to char * is not const safe (arg. no. 1) stru.cpp 28 Error 1058: Initializing a non-const reference 'istream &' with a non-lvalue PC-Lint tells you that you can't pass a temporary to a non const reference which you do in your operator >> for type mine. If you add const to your first (working) line than you will also get a error (also misleading error message but due to const). In that case my PC-Lint tells me --- Module: stru.cpp _ const istrstream in("106"); stru.cpp 24 Info 1776: Converting a string literal to char * is not const safe (arg. no. 1) _ if (in >> mm) stru.cpp 25 Warning 1561: Reference initialization causes loss of const/volatile integrity (arg. no. 1) I don't yet know why this is only flagged as a warning and not a error which it should be in my opinion. - Heinz
Apr 23 2004
↑ ↓ → "Steve Strand" <snstrand comcast.net> writes:
Thank you Heinz! Your answer is helpful and insightful.

Steve
Apr 23 2004