|
Boost : |
From: Alberto Ganesh Barbati (abarbati_at_[hidden])
Date: 2005-10-25 03:27:53
Hi,
I started using the iostreams library for a pet project. I thinks it's a
great piece of software. However, I immediately stumbled in what I think
it may be a defect. Consider this simple source device:
#include <boost/iostreams/stream.hpp>
struct Source : boost::noncopyable
{
typedef char char_type;
typedef boost::iostreams::source_tag category;
Source(int); // ctor
std::streamsize read(char* s, std::streamsize n)
{
// implementation here
}
private:
/* ... private members here */
};
int main()
{
boost::iostreams::stream<Source> s(0);
}
the boost::noncopyable up there has been put because the device keeps
handles to OS resources whose duplication can be very expensive. I was
amazed that the code above doesn't compile. This is the error message
reported by VC7.1:
C:\lib\Boost\include\boost-1_33\boost\iostreams\detail\wrap_unwrap.hpp(52)
: error C2558: struct 'Source' : no copy constructor available or copy
constructor is declared 'explicit'
(full error message is very long and is reported, for reference, at the
end of the message)
It seems that a device must be copy-constructibile. In particular, the
code above makes at least three short-lived copies of the device.
Question is: why? I believe this requirement is unintended and not due
to a conscious design choice, my arguments are:
1) it's not documented, there is no mention of such requirement in
http://www.boost.org/libs/iostreams/doc/concepts/device.html
2) it's unnatural and I believe my case (where copying the device could
be expensive) occurs more often in practice than the opposite case
3) from the error messages it seems that a copy is only required as a
side-effect of the template machinery used in BOOST_IOSTREAMS_FORWARD.
In fact, the offending line detail\wrap_unwrap.hpp(52) is:
inline T wrap(const T& t BOOST_IOSTREAMS_DISABLE_IF_STREAM(T))
{ return t; }
that requires T to be copy-constructible.
Am I missing something?
Thanks in advance,
Ganesh
----- full error messaage follows
C:\lib\Boost\include\boost-1_33\boost\iostreams\detail\wrap_unwrap.hpp(52)
: error C2558: struct 'Source' : no copy constructor available or copy
constructor is declared 'explicit'
C:\lib\Boost\include\boost-1_33\boost\iostreams\stream_buffer.hpp(90) :
see reference to function template instantiation 'T
boost::iostreams::detail::wrap<T>(const T
&,boost::disable_if_c<B,void>::type *)' being compiled
with
[
T=Source,
B=false
]
C:\lib\Boost\include\boost-1_33\boost\iostreams\stream_buffer.hpp(90) :
while compiling class-template member function 'void
boost::iostreams::stream_buffer<T,Tr,Alloc>::open(const T &,int,int)'
with
[
T=Source,
Tr=std::char_traits<char>,
Alloc=std::allocator<char>
]
C:\lib\Boost\include\boost-1_33\boost\utility\base_from_member.hpp(69) :
see reference to class template instantiation
'boost::iostreams::stream_buffer<T,Tr,Alloc>' being compiled
with
[
T=Source,
Tr=std::char_traits<char>,
Alloc=std::allocator<char>
]
C:\lib\Boost\include\boost-1_33\boost\iostreams\stream.hpp(61) :
see reference to class template instantiation
'boost::base_from_member<MemberType>' being compiled
with
[
MemberType=boost::iostreams::stream_buffer<Source,std::char_traits<char>,std::allocator<char>>
]
C:\lib\Boost\include\boost-1_33\boost\iostreams\stream.hpp(98) :
see reference to class template instantiation
'boost::iostreams::detail::stream_base<Device,Tr,Alloc>' being compiled
with
[
Device=Source,
Tr=std::char_traits<char>,
Alloc=std::allocator<char>
]
TestVc2.cpp(26) : see reference to class template instantiation
'boost::iostreams::stream<Device>' being compiled
with
[
Device=Source
]
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk