basic_ostream::operator<<
basic_ostream::operator<< (문자 · 문자열 삽입)
출력 스트림에 문자나 문자 배열을 삽입하는 삽입 연산자(<<)들이에요. std::basic_ostream 계열이 문자·문자열 출력을 처리하는 방법을 정의해요. C++11부터 rvalue 스트림 버전도 있어요.
출처: cppreference
본문
<ostream> 헤더에 정의돼 있고, 문자 계열 삽입용 오버로드예요.
template< class CharT, class Traits >
basic_ostream<CharT, Traits>&
operator<<( basic_ostream<CharT, Traits>& os, CharT ch ); // (1)
template< class CharT, class Traits >
basic_ostream<CharT, Traits>&
operator<<( basic_ostream<CharT, Traits>& os, const CharT* s ); // (2)
template< class Ostream, class T >
Ostream&& operator<<( Ostream&& os, const T& value ); // (3) (since C++11)
- (1) 문자를 삽입해요.
- (2) 문자 배열에서
s가 가리키는 첫 원소부터 연속된 문자들을 삽입해요. - (3) 출력 스트림 객체의 rvalue 참조가 주어졌을 때 적절한 삽입 연산자를 호출해요(
os << value와 같음).os << value식이 well-formed이고Ostream이std::ios_base에서 공개적이고 명확하게 파생된 클래스 타입일 때만 오버로드 해석에 참여해요. - (4) (C++20부터)
wchar_t,char8_t,char16_t,char32_t등(또는 그 널 종료 시퀀스)을 받는 오버로드는 삭제돼요.std::cout << u'X'는 허용되지 않아요. 이전에는 이게 정수나 포인터 값을 출력했어요.
(1)은 FormattedOutputFunction처럼 동작해요. sentry 객체를 만들고 검사한 뒤 문자 ch를 삽입해요. ch가 char 타입이고 os의 문자 컨테이너 타입이 char가 아니면 os.widen(ch)가 대신 삽입돼요.
패딩은 다음과 같이 결정돼요. os.width() > 1이면 os.width() - 1개만큼의 os.fill() 복사본이 출력 문자에 더해져 출력 문자 시퀀스를 만들어요. (out.flags() & std::ios_base::adjustfield) == std::ios_base::left면 채움 문자가 출력 문자 뒤에, 아니면 앞에 배치돼요. 삽입 후 os.width(0)을 호출해 std::setw의 효과가 있으면 취소해요.
(2)에서는 삽입 전에 먼저 모든 문자를 os.widen()으로 넓힌 뒤 패딩을 결정해요. 삽입할 문자 수가 os.width()보다 작으면 문자 시퀀스 길이가 os.width()가 되도록 충분한 os.fill() 복사본을 더해요. s가 널 포인터면 동작이 정의되지 않아요.
- 매개변수
os: 데이터를 삽입할 출력 스트림.ch: 삽입할 문자.s: 삽입할 문자 배열 포인터. - 반환 값: (1,2)
os, (3)std::move(os).
참고로 LWG 1203 이전에는 (std::ostringstream() << 1.2).str() 같은 코드가 컴파일되지 않았어요. rvalue 스트림 오버로드가 추가되면서 이제 동작해요.
예제를 보면요.
#include <fstream>
#include <iostream>
std::ostream& operator<<(std::ostream& os, char8_t const& ch)
{
return os << static_cast<char>(ch);
}
int main()
{
std::cout << "Hello, world" // `const char*` 오버로드 사용
<< '\n'; // `char` 오버로드 사용
std::ofstream{"test.txt"} << 1.2; // rvalue 오버로드 사용
std::cout << u8'!' << '\n'; // 사용자 정의 operator<<(os, char8_t const&) 사용
}
결함 보고로 LWG 167(C++98, (2)의 모든 오버로드에서 삽입 문자가 traits::length(s)였음 → CharT가 ch 타입과 일치하지 않는 오버로드의 수를 갱신), LWG 1203(C++11, rvalue 스트림 오버로드가 기반 클래스의 lvalue 참조 반환 → 파생 클래스의 rvalue 참조 반환), LWG 2011(C++98, 패딩이 std::num_put::do_put()으로 결정됨 → 연산자 자신이 결정), LWG 2534(C++11, rvalue 오버로드가 제약되지 않음 → 제약 추가) 등이 있어요.