2013-12-20 9 views
3

boost :: iostreams를 사용하여 데이터를 압축하려고합니다.boost :: iostreams :: copy()는 소스를 닫지 만 싱크는 닫지 않습니다.

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는 여전히 열려 있음을 볼 수 있습니다. 내 질문은 : 왜? boost :: iostreams :: close()는 filtering_streambuf 객체를 전달할 때 무엇을합니까?

답변

4

흥미 롭습니다.

[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 코드를 읽기

는 :

  1. 실제로 다른 태그를 반환하고 그것을 만들 std::ofstream에 대한 close_tag<>의 전문화를 정의

    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; 
    }; 
    

    몇 가지 해결 방법이 마음에 와서 그래서 닫힌다. (Boost Iostreams의 개발자가 가지고있는 가정에 반대하여 의도하지 않은 결과를 가질 수 있기 때문에 나는 이것을 반대한다.)

  2. ,
  3. 출력 스트림에 대한 부스트 클래스를 사용

#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] 그것은 의외로 많은 토끼 구멍이다보기 , 나는 덧붙여 야한다. 나는이 일반성이 실제로 갖는 모든 이점을 궁금해한다.

+0

위대한 대답, 감사합니다; 나는 문서의 어떤 부분이 문서화되어 있는지뿐만 아니라이 행동의이면에있는 이론적 근거를 이해하는 데 어려움을 겪고있다. 부스트 개발자에게이 질문에 대한 답변을 얻으려고 할 가치가 있다고 생각합니까? – fireboot

+0

@fireboot 그렇게 생각합니다. 그것은 의도적 인 것처럼 보입니다. 문서는 *** [close'의 문서] (http://www.boost.org/doc/libs/1_55_0/libs/iostreams/doc/functions/close.html#template_params_devices)를 참조합니다. *** 닫을 수없는 어떤 것에 대해서도 "플러시"합니다. – sehe