basic_ostream::sentry

basic_ostream::sentry (출력 전 스트림 준비)

std::basic_ostream의 각 출력 멤버 함수가 시작할 때 로컬 스코프에서 생성하는 보조 객체예요. 출력 전에 스트림 상태를 확인하고, tied 출력 스트림을 비우는 등 준비 작업을 수행해요.

출처: cppreference

본문

basic_ostream::sentry 타입의 객체는 std::basic_ostream에서 출력을 수행하는(형식화·비형식화 모두) 각 멤버 함수의 시작 부분에 로컬 스코프에서 생성돼요.

class sentry;

생성자가 출력 스트림을 준비해요. 스트림이 이미 실패 상태인지 확인하고, tie()된 출력 스트림을 비우며, 필요하면 기타 구현 정의 작업을 수행해요. 구현 정의 정리와 필요한 경우 출력 스트림 비우기는 소멸자에서 수행되므로, 출력 중에 예외가 던져져도 보장돼요.

멤버:

  • 생성자: sentry 객체를 만들며 모든 준비 작업을 수행해요.
  • 소멸자: 형식화 출력 후 또는 예외 후 필요하면 스트림 객체를 마무리해요.
  • operator=: 삭제된 대입 연산자.
  • operator bool: 스트림 객체 준비가 성공했는지 확인해요.

std::basic_ostream::sentry::sentry

explicit sentry( std::basic_ostream<CharT, Traits>& os );

형식화 출력을 위해 스트림을 준비해요.

os.good()false면 반환해요. 그렇지 않으면 os.tie()가 널 포인터가 아닐 때 os.tie()->flush()를 호출해 출력 시퀀스를 외부 스트림과 동기화해요. 준비 중에 생성자는 setstate(failbit)를 호출할 수 있어요(std::ios_base::failure를 던질 수 있음).

준비가 끝난 뒤 os.good() == true라면 이후 operator bool 호출은 true를 돌려줘요.

  • 매개변수 os: 준비할 출력 스트림.
  • 예외: 파일 끝 조건이 발생하면 std::ios_base::failure.

std::basic_ostream::sentry::~sentry

~sentry();

((os.flags() & std::ios_base::unitbuf) && !std::uncaught_exception() && os.good())trueos.rdbuf()->pubsync()를 호출해요. 그 함수가 -1을 반환하면 예외를 전파하지 않고 os.rdstate()badbit를 설정해요.

std::basic_ostream::sentry::operator bool

explicit operator bool() const;

출력 스트림 준비가 성공했는지 확인해요.

  • 반환 값: 출력 스트림 준비가 성공했으면 true, 아니면 false.

예제를 보면, operator<< 안에서 sentry를 만들어 준비 상태를 확인한 뒤 write를 수행해요.

#include <iostream>
#include <sstream>

struct Foo
{
    char n[6];
};

std::ostream& operator<<(std::ostream& os, Foo& f)
{
    std::ostream::sentry s(os);
    if (s)
        os.write(f.n, 5);
    return os;
}

int main()
{
    Foo f = {"abcde"};
    std::cout << f << '\n';
}

출력은 abcde예요.

결함 보고로 LWG 397(C++98, 소멸자가 예외를 던질 수 있는 os.flush()를 호출할 수 있었음 → 예외 전파 안 함), LWG 442(C++98, operator bool이 const로 선언되지 않음(동의어에는 const) → const 추가), LWG 835(C++98, os가 unitbuf를 설정하면 소멸자가 os.flush()를 호출하는데, 이는 UnformattedOutputFunction이라 또 다른 sentry 객체를 만들고 그 소멸자가 또 만들고... → 이 경우 os.rdbuf()->pubsync() 호출로 대체)가 있어요.

더 알아보기 (Learn more)

cppreference