std::print
std::print (ostream에 형식화 출력)
형식 문자열 fmt에 따라 args를 포맷하고 그 결과를 os 스트림에 삽입하는 함수예요. std::format의 출력 스트림 버전이며 C++23부터 있어요.
출처: cppreference
본문
<ostream> 헤더에 정의돼 있어요. C++23부터 std::print가 도입돼 formatted output을 표준 스트림에 직접 쓸 수 있게 됐어요.
template< class... Args >
void print( std::ostream& os, std::format_string<Args...> fmt, Args&&... args );
형식 문자열 fmt에 따라 args를 포맷하고, 그 결과를 os 스트림에 삽입해요.
일반 리터럴 인코딩이 UTF-8이면 다음과 동일해요.
std::vprint_unicode(os, fmt.get(), std::make_format_args(args...));. 그렇지 않으면,std::vprint_nonunicode(os, fmt.get(), std::make_format_args(args...));.
Args의 어떤 Ti에 대해서도 std::formatter<Ti, char>가 BasicFormatter 요구사항을 만족하지 않으면(std::make_format_args가 요구하는 대로) 동작이 정의되지 않아요.
매개변수
-
os: 데이터를 삽입할 출력 스트림. -
fmt: 형식 문자열을 나타내는 객체. 형식 문자열은 다음으로 구성돼요.- 출력으로 그대로 복사되는 일반 문자(
{와}제외), - 출력에서 각각
{와}로 대체되는 이스케이프 시퀀스{{와}}, - replacement fields.
각 replacement field는 다음 형식을 가져요.
{ arg-id (optional) }(1),{ arg-id (optional) : format-spec }(2).- (1) 형식 지정 없는 replacement field. (2) 형식 지정 있는 replacement field.
arg-id: 포맷에 사용할args안 인자의 인덱스를 지정해요. 생략하면 인자들이 순서대로 사용돼요. 형식 문자열의arg-id들은 모두 있거나 모두 생략돼야 해요. 수동 인덱싱과 자동 인덱싱을 섞는 건 오류예요.format-spec: 해당 인자에 대한std::formatter특수화가 정의한 형식 지정이에요.}로 시작할 수 없어요. 기본 타입·표준 문자열 타입은 표준 형식 지정, chrono 타입은 chrono 형식 지정, range 타입은 range 형식 지정,std::pair·std::tuple은 tuple 형식 지정으로 해석돼요.std::filesystem::path는 path 형식 지정(C++26)을, 그 외 포맷 가능 타입은 사용자 정의 formatter 특수화가 결정해요.
- 출력으로 그대로 복사되는 일반 문자(
-
args...: 포맷할 인자들.
예외
- 할당 실패 시
std::bad_alloc. - 어떤 formatter가 던지는 예외(예:
std::format_error)는os.exceptions()값과 무관하게,os의 오류 상태에서ios_base::badbit를 켜지 않고 전파돼요. os로의 삽입이 실패하면 호출되는os.setstate(ios_base::badbit)때문에 생기는ios_base::failure를 던질 수 있어요.
참고
피처 테스트 매크로 __cpp_lib_print(값 202207L, C++23, Formatted output)와 __cpp_lib_format(값 202207L, C++23, std::basic_format_string 노출)이 있어요.
예제를 보면요.
#include <array>
#include <cctype>
#include <cstdio>
#include <format>
#include <numbers>
#include <ranges>
#include <sstream>
int main()
{
std::array<char, 24> buf;
std::format_to(buf.begin(), "{:.15f}", std::numbers::sqrt2);
unsigned num{}, sum{};
for (auto n : buf
| std::views::filter(isdigit)
| std::views::transform([](char x) { return x - '0'; })
| std::views::take_while([&sum](char) { return sum < 42; }))
sum += n, ++num;
std::stringstream stream;
#ifdef __cpp_lib_print
std::print(stream,
#else
stream << std::format(
#endif
"√2 ≈ {0}.\n"
"The sum of its first {1} digits is {2}.",
std::numbers::sqrt2, num, sum
);
std::puts(stream.str().data());
}
출력은 다음과 같아요.
√2 ≈ 1.4142135623730951.
The sum of its first 13 digits is 42.
이렇게 std::print는 std::format처럼 형식 지정을 지원하면서도 바로 ostream에 결과를 써줘요.