basic_istream::sentry
basic_istream::sentry (입력 전 스트림 준비)
std::basic_istream의 각 입력 멤버 함수가 시작할 때 로컬 스코프에서 생성하는 보조 객체예요. 입력 전에 스트림 상태를 확인하고, tied 출력 스트림을 비우고, 선행 공백을 건너뛰는 등 준비 작업을 수행해요.
출처: cppreference
본문
basic_istream::sentry 타입의 객체는 std::basic_istream에서 입력을 수행하는(형식화·비형식화 모두) 각 멤버 함수의 시작 부분에 로컬 스코프에서 생성돼요.
class sentry;
생성자가 입력 스트림을 준비해요. 스트림이 이미 실패 상태인지 확인하고, tie()된 출력 스트림을 비우며, noskipws 플래그가 설정돼 있지 않으면 선행 공백을 건너뛰고, 필요하면 기타 구현 정의 작업을 수행해요. 필요한 모든 정리는 소멸자에서 수행되므로, 입력 중에 예외가 던져져도 정리가 보장돼요.
멤버:
traits_type=Traits.- 생성자: sentry 객체를 만들며 모든 준비 작업을 수행해요.
- 소멸자: 형식화 입력 후 또는 예외 후 필요하면 스트림 객체를 마무리해요.
operator=[deleted]: 복사 대입 불가.operator bool: 스트림 객체 준비가 성공했는지 확인해요.
std::basic_istream::sentry::sentry
explicit sentry( std::basic_istream<CharT, Traits>& is, bool noskipws = false );
형식화 입력을 위해 스트림을 준비해요.
is.good()이 false면 is.setstate(std::ios_base::failbit)를 호출하고 반환해요. 그렇지 않으면 is.tie()가 널 포인터가 아닐 때 is.tie()->flush()를 호출해 출력 시퀀스를 외부 스트림과 동기화해요. is.tie()의 put 영역이 비어 있으면 이 호출을 생략할 수 있어요. 구현은 flush() 호출을 is.rdbuf()->underflow() 호출 시점까지 미룰 수 있고, sentry 객체가 파괴되기 전에 그런 호출이 없으면 아예 제거해도 돼요.
noskipws가 0이고 is.flags() & std::ios_base::skipws가 0이 아니면, 다음에 사용할 수 있는 문자가 공백이 아닐 때까지 모든 공백 문자를 추출해 버려요(is에 현재 부여된 로케일로 판정). is.rdbuf()->sbumpc()나 is.rdbuf()->sgetc()가 traits::eof()를 돌려주면 setstate(std::ios_base::failbit | std::ios_base::eofbit)를 호출해요(이는 std::ios_base::failure를 던질 수 있어요).
추가로 구현 정의 준비 작업이 일어날 수 있고, 이는 setstate(std::ios_base::failbit)를 호출할 수 있어요(역시 std::ios_base::failure를 던질 수 있어요).
준비가 끝난 뒤 is.good() == true라면 이후 operator bool 호출은 true를 돌려줘요.
- 매개변수
is: 준비할 입력 스트림.noskipws: 공백을 건너뛰지 말아야 하면true. - 예외: 공백을 건너뛰는 중 파일 끝 조건이 발생하면
std::ios_base::failure.
std::basic_istream::sentry::~sentry
~sentry();
아무것도 하지 않아요.
std::basic_istream::sentry::operator bool
explicit operator bool() const;
입력 스트림 준비가 성공했는지 확인해요.
- 반환 값: 입력 스트림 초기화가 성공했으면
true, 아니면false.
예제를 보면, operator>> 안에서 sentry를 만들어 준비 상태를 확인한 뒤 read를 수행해요.
#include <iostream>
#include <sstream>
struct Foo
{
char n[5];
};
std::istream& operator>>(std::istream& is, Foo& f)
{
std::istream::sentry s(is);
if (s)
is.read(f.n, 5);
return is;
}
int main()
{
std::string input = " abcde";
std::istringstream stream(input);
Foo f;
stream >> f;
std::cout.write(f.n, 5);
std::cout << '\n';
}
출력은 abcde예요. 선행 공백이 sentry에서 건너뛰어진 뒤 5글자가 읽혀요.
결함 보고로 LWG 195(C++98, 생성자가 eofbit를 설정할지 불명확 → 명확히 함)와 LWG 419(C++98, 생성자가 eofbit가 설정됐을 때 failbit를 설정하지 않음 → 이 경우 설정)가 있어요.