Description
When specializing std::formatter
is can be useful to call std::format_to(format_context.out(), ...)
to actually do the formatting.
In fact the Working Draft includes an example that does just that.
But when attempting to do so I get the following error: format(1816,15): error: no member named 'resize' in 'std::_Fmt_buffer<char>'
.
Test case
#include <format>
struct wrapper {
int value;
};
template<typename CharT>
struct std::formatter<wrapper, CharT> {
auto parse(auto &context) const {
auto it = context.begin();
if (it != context.end() && *it != CharT{'}'}) {
throw format_error{"invalid format specification"};
}
return it;
}
auto format(const wrapper wrap, auto &context) const {
return format_to(context.out(), "{}", wrap.value);
}
};
auto main() -> int {
std::format("{}", wrapper{123});
}
The full error message from Clang (MSVC fails the in exact same way)
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30037\include\format(1816,15): error: no member named 'resize' in 'std::_Fmt_buffer<char>'
_Cont.resize(_Capacity);
~~~~~ ^
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30037\include\format(1824,14): note: in instantiation of member function 'std::_Fmt_iterator_buffer<std::back_insert_iterator<std::_Fmt_buffer<char>>, char>::_Grow' requested here
explicit _Fmt_iterator_buffer(back_insert_iterator<_Container> _Out, ptrdiff_t = 0)
^
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30037\include\format(2897,43): note: in instantiation of member function 'std::_Fmt_iterator_buffer<std::back_insert_iterator<std::_Fmt_buffer<char>>, char>::_Fmt_iterator_buffer' requested here
_Fmt_iterator_buffer<_OutputIt, char> _Buf(_STD move(_Out));
^
main.cpp(87,16): note: in instantiation of function template specialization 'std::format_to<std::back_insert_iterator<std::_Fmt_buffer<char>>, int>' requested here
return format_to(context.out(), "{}", wrap.value);
^
main.cpp(92,10): note: in instantiation of function template specialization 'std::format<wrapper>' requested here
std::format("{}", wrapper{123});
^
I'm pretty sure the problem is that the _Fmt_iterator_buffer<back_insert_iterator<_Container>, ...>
specialization is not sufficiently constrained.
_Fmt_iterator_buffer::_Grow
calls _Cont::resize
here:
Lines 1816 to 1818 in 4c862ee
But the constraint on the specialization does not check for
resize
being available: Lines 1800 to 1803 in 4c862ee
Considering that the specialization in question is meant to optimize for contiguous output buffers and _Fmt_buffer
is contiguous, it would seem reasonable to add a resize
member function to _Fmt_buffer
(or maybe there should even be a separate specialization for _Fmt_buffer
).