Интересно.
Спускаясь по кроличьей норе[1], оказывается, что close_impl<any_tag>
наконец-то достигнуто для ofstream, заключенного глубоко внутри chain_buf внутри filtering_streambuf. Реализация гласит:
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;
};
На ум приходят несколько обходных путей:
определить специализацию close_tag<>
для std::ofstream
, которая на самом деле возвращает другой тег, и сделать так, чтобы он закрывался (я не рекомендую этого делать, поскольку это может иметь непреднамеренные последствия, противореча предположениям разработчиков Boost Iostreams)
используйте класс повышения для выходного потока:
#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;
}
Смотрите Прямой эфир на Coliru
[1] Должен добавить, что это удивительно большая кроличья нора. Интересно, какую пользу на самом деле несет вся эта универсальность?
person
sehe
schedule
20.12.2013