我正在尝试使用istream
将boost
与progress_display
的{{1}}打包在一起boost::iterator_adaptor
。我写的是
class ifstreamWithProgress: public boost::iterator_adaptor <
ifstreamWithProgress,
char*,
boost::use_default,
boost::forward_traversal_tag > {
public:
// ifstreamWithProgress(const char* fname_) {}
ifstreamWithProgress(): iter(std::istream_iterator<char>()), pd(0)
{}
ifstreamWithProgress(const std::string& fname_): fname(fname_), fsize(0), pd(fsize) {
std::ifstream file(fname.c_str(), std::ios::binary);
fsize = file.tellg();
file.seekg(0, std::ios::end);
fsize = file.tellg() - fsize;
file.seekg(0, std::ios::beg);
iter = std::istream_iterator<char>(file);
pd.restart(fsize);
}
~ifstreamWithProgress() {
while( ++pd < fsize);
}
const std::istream_iterator<char> getRawIstream() const {
return iter;
}
private:
std::string fname;
friend class boost::iterator_core_access;
std::istream_iterator<char> iter;
std::streampos fsize;
progress_display pd;
void increments() {
iter++;
++pd;
}
bool equal(const ifstreamWithProgress& rhs) const {
return this->iter == rhs.getRawIstream();
}
};
这个编译。但是,当我开始做类似
的事情 ifstreamWithProgress is("data.txt");
ifstreamWithProgress eos;
is != eos;
我收到编译时错误,说它不可复制。这有一定意义,因为显示类派生自boost::noncopyable
。然而,我没有得到的是复制发生的地方。有什么指针吗?
PS:错误信息是
1>c:\users\leon.sit\documents\myprojects\c++\general_models\phoenixdsm\phx\fileProgressBarWrapper.hpp(58) : error C2248: 'boost::noncopyable_::noncopyable::noncopyable' : cannot access private member declared in class 'boost::noncopyable_::noncopyable'
1> C:\Program Files\boost\boost_1_44\boost/noncopyable.hpp(27) : see declaration of 'boost::noncopyable_::noncopyable::noncopyable'
1> C:\Program Files\boost\boost_1_44\boost/noncopyable.hpp(22) : see declaration of 'boost::noncopyable_::noncopyable'
1> This diagnostic occurred in the compiler generated function 'ifstreamWithProgress::ifstreamWithProgress(const ifstreamWithProgress &)'
并未指向源中的任何位置。然而,它在评论比较线后编译。
答案 0 :(得分:1)
不必在任何地方进行复制以产生此错误。它简单地反映了编译器必须生成复制构造函数的事实。但要做到这一点,它也必须复制progress_display
,这是不可能的,因为后者的复制构造函数是私有的。
您可以通过声明指向progress_display
成员的指针并定义自己的复制构造函数和=运算符来解决此问题。例如:
class ifstreamWithProgress: public boost::iterator_adaptor <
ifstreamWithProgress,
char*,
boost::use_default,
boost::forward_traversal_tag > {
public:
ifstreamWithProgress() : pd(0) {
pd = new progress_display(...);
}
ifstreamWithProgress::ifstreamWithProgress(const ifstreamWithProgress &r) : pd(0) {
pd = new progress_display(...);
}
~ifstreamWithProgress() {
if (0 != pd) {
delete pd;
}
}
ifstreamWithProgress& operator= (const ifstreamWithProgress &r) {
if (0 != pd) {
delete pd;
}
pd = new progress_display(...);
return *this;
}
private:
progress_display *pd;
};
或者您可以使用shared_ptr<progress_display>
。
答案 1 :(得分:1)
迭代器旨在成为可以复制的轻量级对象。接受迭代器的所有标准实用程序都通过值参数获取它们。 operator !=
定义的不等式boost_adaptor
也不例外。因此:
is != eos;
匹配
bool operator != (ifstreamWithProgress, ifstreamWithProgress);
(或其中一个等价物)。这会调用ifstreamWithProgress
的复制构造函数,而后者又无法生成,因为您的某个成员不可复制。