gpt4 book ai didi

c++ - boost::iostreams::copy() 关闭源而不是接收器

转载 作者:太空狗 更新时间:2023-10-29 21:00:50 25 4
gpt4 key购买 nike

我正在尝试使用 boost::iostreams 来压缩数据。

copy() 的文档表示它的两个参数最后通过调用模板函数关闭 close()在他们两个上。我的测试代码是:

#include <iostream>
#include <fstream>

#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/filter/gzip.hpp>

using namespace std;

int main(void)
{
ifstream ifs("output", ios::binary);
ofstream ofs("output.boost.gz", ios::binary);

boost::iostreams::filtering_streambuf<boost::iostreams::output> out;

out.push(boost::iostreams::gzip_compressor());
out.push(ofs);

cout << (ifs.is_open() ? "ifs is opened" : "ifs not opened") << endl;
cout << (ofs.is_open() ? "ofs is opened" : "ofs not opened") << endl;

boost::iostreams::copy(ifs, out);

cout << (ifs.is_open() ? "ifs is opened" : "ifs not opened") << endl;
cout << (ofs.is_open() ? "ofs is opened" : "ofs not opened") << endl;

return 0;
}

这个测试输出:

ifs is opened
ofs is opened
ifs not opened
ofs is opened

可以看到ofs还是打开的。我的问题是:为什么?当传递一个 filtering_streambuf 对象时,boost::iostreams::close() 做了什么?

最佳答案

有趣。

走下兔子洞[1] 结果是close_impl<any_tag>最终到达 filtering_streambuf 内的 chain_buf 深处的 ofstream。实现如下:

template<>
struct close_impl<any_tag> {
template<typename T>
static void close(T& t, BOOST_IOS::openmode which)
{
if (which == BOOST_IOS::out)
iostreams::flush(t);
}

template<typename T, typename Sink>
static void close(T& t, Sink& snk, BOOST_IOS::openmode which)
{
if (which == BOOST_IOS::out) {
non_blocking_adapter<Sink> nb(snk);
iostreams::flush(t, nb);
}
}
};

因此,如您所见,记录的行为实际上只是刷新了链接的输出流缓冲区(在该调用之前,包含实体上还有一个同步,IIRC) .

我完全同意,这本可以更加明确。

阅读决定特化的 TMP 代码:

template<typename T>
struct close_tag {
typedef typename category_of<T>::type category;
typedef typename detail::unwrapped_type<T>::type unwrapped;
typedef typename
iostreams::select<
mpl::not_< is_convertible<category, closable_tag> >,
any_tag,
mpl::or_<
is_boost_stream<unwrapped>,
is_boost_stream_buffer<unwrapped>
>,
close_boost_stream,
mpl::or_<
is_filtering_stream<unwrapped>,
is_filtering_streambuf<unwrapped>
>,
close_filtering_stream,
mpl::or_<
is_convertible<category, two_sequence>,
is_convertible<category, dual_use>
>,
two_sequence,
else_,
closable_tag
>::type type;
};

我想到了几种解决方法:

  1. 定义 close_tag<> 的特化对于 std::ofstream实际上返回一个不同的标签并使其关闭(我建议不要这样做,因为它可能会因违背 Boost Iostreams 开发人员所持有的假设而产生意想不到的效果)

  2. 为输出流使用 boost 类:

#include <iostream>
#include <fstream>

#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/device/file.hpp>
#include <boost/iostreams/filter/gzip.hpp>

using namespace std;

int main(void)
{
cout << boolalpha;

ifstream ifs("output", ios::binary);
boost::iostreams::file_sink ofile("output.boost.gz");

boost::iostreams::filtering_streambuf<boost::iostreams::output> out;
out.set_auto_close(true);

out.push(boost::iostreams::gzip_compressor());
out.push(ofile);

cout << "out.is_complete(): " << out.is_complete() << endl;
cout << "ifs.is_open()? " << ifs.is_open() << endl;
cout << "ofile.is_open()? " << ofile.is_open() << endl;

boost::iostreams::copy(ifs, out);

cout << "out.is_complete(): " << out.is_complete() << endl;
cout << "ifs.is_open()? " << ifs.is_open() << endl;
cout << "ofile.is_open()? " << ofile.is_open() << endl;
}

查看 Live on Coliru


[1] 这是一个大得惊人的兔子洞,我必须补充一下。我想知道所有这些通用性到底有什么好处

关于c++ - boost::iostreams::copy() 关闭源而不是接收器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20707968/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com