C++11 문법 기준으로 문자열을 formatting 하는 템플릿 함수를 만들어봤다. 메모 겸 올려본다.
(C++20부터는 std::format이 추가되었으므로 그걸 쓰면 된다.)
기본적인 틀은 아래 글을 참고하여 작성했다.
https://stackoverflow.com/questions/2342162/stdstring-formatting-like-sprintf
참고한 코드 대비해서 좋은 점은 아래와 같다.
1. std::string, std::wstring에 대해 모두 사용가능
2. 참고한 코드 대비 메모리 할당/복사가 적음
format.hpp
#include <string>
#include <stdexcept>
#include <cstdio>
#if defined _MSC_VER && _MSC_VER <= 1800
// Visual studio 2013에서는 C++11은 지원되지만 std::snprintf가
// 정의되어 있지 않기 때문에 명시적으로 정의해준다.
namespace std
{
template<class ... Args>
static int snprintf(char* _Buffer, int _BufferCount, const char* _Fomat, Args&&... args)
{
return _snprintf(_Buffer, _BufferCount, _Fomat, std::forward<Args>(args)...);
}
}
#endif
template<class char_t>
struct _FormatFunction{};
template<>
struct _FormatFunction<char>
{
template<class ... Args>
int operator()(Args&&... args)
{
return std::snprintf(std::forward<Args>(args)...);
}
}
template<>
struct _FormatFunction<wchar_t>
{
template<class ... Args>
int operator()(Args&&... args)
{
return std::swprintf(std::forward<Args>(args)...);
}
}
// 아래 글을 참고하여 작성함.
// https://stackoverflow.com/questions/2342162/stdstring-formatting-like-sprintf
template<class char_t, typename... Args>
std::basic_string<char_t> format(const std::basic_string<char_t>& fmt, Args&&... args)
{
if(fmt.size() == 0 || sizeof...(Args) == 0)
return fmt;
_FormatFunction<char_t> func{};
int size_s = func(nullptr, 0, fmt.c_str(), args...);
if(size_s <= 0)
throw std::runtime_error("Error during formatting.");
// null-terminator 가 포함되지 않은 사이즈
auto size = static_cast<size_t>(size_s);
// C++11 이후부터, std::string/std::wstring은 null-terminated 되는 것이 보장 되어있다.
// (https://stackoverflow.com/questions/11752705/does-stdstring-have-a-null-terminator)
// 따라서 ret의 실제 버퍼에는 null-terminator가 포함된다
std::basic_string<char_t> ret(size, 0);
// 버퍼 사이즈는 null-terminator 를 포함한 사이즈 (size + 1)를 전달해야 한다.
func(&ret[0], (size + 1) * sizeof(char_t), fmt.c_str(), args...);
return ret;
}
예시
int x = 10, y = -30;
std::string str = format("x: %d, y: %d", x, y); // "x: 10, y: -30"
std::wstring wstr = format(L"x: %d, y: %d", x, y); // L"x: 10, y: -30"
'도서 리뷰' 카테고리의 다른 글
[도서 리뷰] 예제로 배우는 CUDA 프로그래밍 (0) | 2021.10.07 |
---|---|
[도서 리뷰] 대규모 병렬 프로세서 프로그래밍 (0) | 2021.10.07 |
[도서 리뷰] Effective C++(이펙티브 C++) (1) | 2021.10.07 |
[도서 리뷰] 가상화폐 투자 마법 공식 (0) | 2021.10.07 |
[도서 리뷰] Effective Modern C++ (이펙티브 모던 C++) (1) | 2021.10.07 |