std::iostream/std::cout - Do not compile with vc-8_0

  • Thread starter jean.daniel.michaud
  • Start date
J

jean.daniel.michaud

Hi all,

Something I don't get.
The code is:

// snippet on
#include <list>
#include <iostream>

int main()
{
std::list<std::eek:stream> list;
list.push_back(std::cout);
return 0
}
// snippet off

Compiles with msvc (visual 6) but not with vc-8_0 (visual 2005).

vc-8_0 output (C:\>cl /EHsc test.cpp) :

// output on
test.cpp
G:\Program Files\Microsoft Visual Studio 8\VC\INCLUDE\ostream(581) :
error C2248: 'std::basic_ios<_Elem,_Traits>::basic_ios' : cannot
access private member declared in class
'std::basic_ios<_Elem,_Traits>'
with
[
_Elem=char,
_Traits=std::char_traits<char>
]
G:\Program Files\Microsoft Visual Studio 8\VC\INCLUDE
\ios(151) : see declaration of
'std::basic_ios<_Elem,_Traits>::basic_ios'
with
[
_Elem=char,
_Traits=std::char_traits<char>
]
This diagnostic occurred in the compiler generated function
'std::basic_ostream<_Elem,_Traits>::basic_ostream(const
std::basic_ostream<_Elem,_Traits> &)'
with
[
_Elem=char,
_Traits=std::char_traits<char>
]
// output off

Why ? std::cout is supposed to be a std::eek:stream right ? I tried a
static_cast<std::eek:stream &>, but no luck...

Any idea?

JD
 
M

Mike Wahler

Hi all,

Something I don't get.
The code is:

// snippet on
#include <list>
#include <iostream>

int main()
{
std::list<std::eek:stream> list;
list.push_back(std::cout);
return 0
}
// snippet off

Compiles with msvc (visual 6) but not with vc-8_0 (visual 2005).

vc-8_0 output (C:\>cl /EHsc test.cpp) :

// output on
test.cpp
G:\Program Files\Microsoft Visual Studio 8\VC\INCLUDE\ostream(581) :
error C2248: 'std::basic_ios<_Elem,_Traits>::basic_ios' : cannot
access private member declared in class
'std::basic_ios<_Elem,_Traits>'
with
[
_Elem=char,
_Traits=std::char_traits<char>
]
G:\Program Files\Microsoft Visual Studio 8\VC\INCLUDE
\ios(151) : see declaration of
'std::basic_ios<_Elem,_Traits>::basic_ios'
with
[
_Elem=char,
_Traits=std::char_traits<char>
]
This diagnostic occurred in the compiler generated function
'std::basic_ostream<_Elem,_Traits>::basic_ostream(const
std::basic_ostream<_Elem,_Traits> &)'
with
[
_Elem=char,
_Traits=std::char_traits<char>
]
// output off

Standard library containers (such as std::list) impose requirements
upon the types of object they can contain. These requirements are
that these objects must be copyable and assignable. Stream types
do not meet this requirement. If you must group streams into a
'collection', you'll need to store pointers to them instead of
the stream objects themselves. BTW what specifically is your
intended purpose of using a container of stream objects?
Why ? std::cout is supposed to be a std::eek:stream right ? I tried a
static_cast<std::eek:stream &>, but no luck...

Don't guess. Using a cast to 'fix' a compiler warning or error is
almost always the wrong thing to do.

-Mike
 
J

jean.daniel.michaud

Standard library containers (such as std::list) impose requirements
upon the types of object they can contain. These requirements are
that these objects must be copyable and assignable. Stream types
do not meet this requirement. If you must group streams into a
'collection', you'll need to store pointers to them instead of

Ok, but why msvc would compile it then ? And why this compiles with
vc-8_0:
// snippet on
#include <list>
#include <iostream>

int main()
{
std::list<std::eek:stream> list;
return 0;
}
// snippet off

I have created a list of ostream... It should not compile has ostream
does not satisfies the requirements you enounce.
the stream objects themselves. BTW what specifically is your
intended purpose of using a container of stream objects?

I'm trying to write a log library. This list of streams is just the
list of output for my logger object. Make use of pointers here will
just make the usage of the library harder. User will have to use new,
and therefore delete...
Don't guess. Using a cast to 'fix' a compiler warning or error is
almost always the wrong thing to do.

I know, I saw this on a previous post on the same pb, so I wanted to
step aside this potential answer.

JD
 
V

Victor Bazarov

Ok, but why msvc would compile it then ? And why this compiles with
vc-8_0:
// snippet on
#include <list>
#include <iostream>

int main()
{
std::list<std::eek:stream> list;
return 0;
}
// snippet off

I have created a list of ostream... It should not compile has ostream
does not satisfies the requirements you enounce.

You've not done anything that would actually invoke the code requiring
the functionality 'ostream' lacks. Try pushing anything in.

V
 
F

Fei Liu

Ok, but why msvc would compile it then ? And why this compiles with
vc-8_0:
// snippet on
#include <list>
#include <iostream>

int main()
{
std::list<std::eek:stream> list;
return 0;
}
// snippet off

msvc doesn't actually instantiate any template source code that would
facilitate the missing copy semantic in std::eek:stream. It only
instantiates upon demand.
 
O

Old Wolf

Ok, but why msvc would compile it then ? And why this compiles with
vc-8_0:

Most compilers still compile some programs even though they don't
comply with the C++ standard.
 
J

jean.daniel.michaud

Standard library containers (such as std::list) impose requirements
upon the types of object they can contain. These requirements are
that these objects must be copyable and assignable. Stream types
do not meet this requirement. If you must group streams into a
'collection', you'll need to store pointers to them instead of
the stream objects themselves. BTW what specifically is your
intended purpose of using a container of stream objects?

Ok, so to avoid using pointers, I'm trying the shared_ptr, but I still
have difficulties with ostream.
In this code, I add to a list a reference to an ostream. When I try to
access it, I have a crash.

// Snippet on
#include <list>
#include <string>
#include <iostream>
#include <boost/shared_ptr.hpp>

int main()
{
std::list<boost::shared_ptr<std::eek:stream> > l;

boost::shared_ptr<std::eek:stream> p(&std::cout);
*p << "on the shared pointer" << std::endl;
l.push_back(p);

std::list<boost::shared_ptr<std::eek:stream> >::iterator it =
l.begin();
std::cout << "before loop" << std::endl;
while (it++ != l.end())
{
boost::shared_ptr<std::eek:stream> p2 = *it;
*p2 << "test" << std::endl;
}

return 0;
}
// snippet off

I have somthing like:
// output on
on the shared pointer
before loop
segmentation fault
// output off

dereferencing p2 should give me my ostream. It works on p... Any idea?

JD
 
M

Matteo

Ok, so to avoid using pointers, I'm trying the shared_ptr, but I still
have difficulties with ostream.
In this code, I add to a list a reference to an ostream. When I try to
access it, I have a crash.

// Snippet on
#include <list>
#include <string>
#include <iostream>
#include <boost/shared_ptr.hpp>

int main()
{
std::list<boost::shared_ptr<std::eek:stream> > l;

boost::shared_ptr<std::eek:stream> p(&std::cout);
*p << "on the shared pointer" << std::endl;
l.push_back(p);

std::list<boost::shared_ptr<std::eek:stream> >::iterator it =
l.begin();
std::cout << "before loop" << std::endl;
while (it++ != l.end())
{
boost::shared_ptr<std::eek:stream> p2 = *it;
*p2 << "test" << std::endl;
}

return 0;}

// snippet off

I have somthing like:
// output on
on the shared pointer
before loop
segmentation fault
// output off

dereferencing p2 should give me my ostream. It works on p... Any idea?

JD

First off, a boost::shared_pointer will delete its pointee by default.
You can overcome that by passing in a null deleter to the shared
pointer constructor (details in the boost::shared_ptr docs). With what
you have, the shared pointer will call delete on &cout when the last
shared pointer is destructed (at the end of the program). This will
almost certainly cause a crash of some sort.

I'm not sure why you're getting a segfault before "test" is output,
since std::endl is supposed to flush buffers (I believe). If I'm
wrong, your program could be crashing at program termination due to
what I said above, but before all the buffers are flushed (certainly,
if you had used <<"\n" instead of <<std::endl, thats what I would have
guessed).

I'm not sure that what you are doing is necessarily the best way to
achieve what you want, but as I have no ther suggestions, try using a
null deleter, and report back.

-matt
 
J

jean.daniel.michaud

First off, a boost::shared_pointer will delete its pointee by default.
You can overcome that by passing in a null deleter to the shared
pointer constructor (details in the boost::shared_ptr docs). With what
you have, the shared pointer will call delete on &cout when the last
shared pointer is destructed (at the end of the program). This will
almost certainly cause a crash of some sort.

Yes obviously, I forget that but that is obvious.
Here is the code, that produce the same result.

// snippet on
#include <list>
#include <string>
#include <iostream>
#include <boost/shared_ptr.hpp>

struct null_deleter { void operator()(void const *) const {} };

int main()
{
std::list<boost::shared_ptr<std::eek:stream> > l;

boost::shared_ptr<std::eek:stream> p(&std::cout, null_deleter());
*p << "on the shared pointer" << std::endl;
l.push_back(p);

std::list<boost::shared_ptr<std::eek:stream> >::iterator it =
l.begin();
std::cout << "before loop" << std::endl;
while (it++ != l.end())
{
boost::shared_ptr<std::eek:stream> p2 = *it;
*p2 << "test" << std::endl;
}

return 0;
}
// snippet off
I'm not sure why you're getting a segfault before "test" is output,
since std::endl is supposed to flush buffers (I believe). If I'm
wrong, your program could be crashing at program termination due to
what I said above, but before all the buffers are flushed (certainly,
if you had used <<"\n" instead of <<std::endl, thats what I would have
guessed).

Actually it really crashes on the streaming. I debugged it with gdb.
It crashes on:
std::eek:stream::sentry::sentry () from /usr/lib/libstdc++.so.6
I'm not sure that what you are doing is necessarily the best way to
achieve what you want, but as I have no ther suggestions, try using a
null deleter, and report back.

What I am trying to do is to have a pool of streams where to write on.
The user add streams to the list, pass this to my library, and then I
shall manage deallocation. I don't want the user to mess around with
shared_ptr and I dont want him to allocate pointer either (RIIA, RAAI
or RIAA, I don't remember the term :) ...)

Thanks for your help.

JD
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top