Custom formatter for std::format for std::wstring GCC

172 views Asked by At

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.

Failing with GCC/Clang libstd++

1

There are 1 answers

0
康桓瑋 On

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 for std::formatter is not allowed because it does not depend on program-defined types, although std::wstring with custom traits or allocator classes may be valid options.