I'm trying to make a formatter for std::format
that would take a std::wstring
and format it to a std::string
. The idea being that I'd replace all the non-convertible chars with '?
'.
#include <format>
#include <string>
#include <iostream>
template<>
struct std::formatter<std::wstring> : public std::formatter<std::string> {
template<typename ParsContext>
constexpr auto parse(ParsContext& ctx) {
return std::begin(ctx);
}
template<typename FormatContext>
auto format(const std::wstring &obj, FormatContext &ctx) const {
std::string result{};
for(const auto & wch : obj){
if(wch < 0x80){
std::format_to(std::back_inserter(result), "{}", static_cast<char>(wch));
}else{
std::format_to(std::back_inserter(result), "?");
}
}
return std::formatter<std::string>::format(result, ctx);
}
};
int main(){
std::wstring test{L"Hello wide world.こんにちは、안녕하세요!\n"};
std::cout << std::format("{}", test);
}
Results in the following compiler error: (small sample, full error at compiler explorer)
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/format:3029:19: error: no matching function for call to 'std::basic_string_view<char>::basic_string_view(<brace-enclosed initializer list>)'
3029 | _M_set(_Td{__v.data(), __v.size()});
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/string_view:146:7: note: candidate: 'constexpr std::basic_string_view<_CharT, _Traits>::basic_string_view(const _CharT*, size_type) [with _CharT = char; _Traits = std::char_traits<char>; size_type = long unsigned int]'
146 | basic_string_view(const _CharT* __str, size_type __len) noexcept
| ^~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/string_view:146:39: note: no known conversion for argument 1 from 'wchar_t*' to 'const char*'
146 | basic_string_view(const _CharT* __str, size_type __len) noexcept
Using libc++ with clang it works Working with Clang with libc++
Any help would be appreciated.
This is a bug in libstdc++ (PR 112607) and has been fixed in the GCC-trunk.
Note that as the comments say, specializing
std::wstring
forstd::formatter
is not allowed because it does not depend on program-defined types, althoughstd::wstring
with custom traits or allocator classes may be valid options.