I defined a formatter for std::unique_ptr<T>
in my code, but when I try to print a std::vector<std::unique_ptr<int>>
, I am getting the following compiler error:
std::is_default_constructible_v<std::formatter<std::vector<std::unique_ptr<int, std::default_delete<int> > >, char> >' evaluates to false
Attaching entire code (with Compiler Explorer link):
#include <format>
#include <memory>
#include <vector>
#include <iostream>
template <typename T>
struct std::formatter<std::unique_ptr<T>> : std::formatter<std::string> {
constexpr auto format(const std::unique_ptr<T>& e, std::format_context& ctx) const {
if (e == nullptr)
return std::formatter<std::string>::format("nullptr", ctx);
return std::formatter<std::string>::format(std::format("{0}", *e), ctx);
}
};
int main() {
auto x = std::make_unique<int>(3);
std::cout << std::format("{}", x);
std::vector<std::unique_ptr<int>> vec;
auto s = std::format("{0}", vec);
}
I want to know why the compilation failed, given that formatter for each template types are defined. Additionally, how to generically solve this issue (i.e., do I really need to define a formatter for std::vector<std::unique_ptr<T>>
too?)
This is LWG 4240.
The issue is that the constraint in formattable<T, char>
effectively requires T
to be formattable with any format_context
. Unfortunately, the error diagnostic for getting this wrong is useless — you never see why std::vector<std::unique_ptr<int>>
is not formattable, only that it is not. You just... need to know?
If you change your formatter
to accept any context, instead of specifically std::format_context
, then it will work fine:
- constexpr auto format(const std::unique_ptr<T>& e, std::format_context& ctx) const {
+ constexpr auto format(const std::unique_ptr<T>& e, auto& ctx) const {