I wish to add a custom std::string formatter, so it takes precedence over the default one and I don't have to use formatters for custom types like std::format("{}", Upper(s)).
#include <iostream>
#include <format>
#include <string>
template <>
struct std::formatter<std::string> {
constexpr auto parse(std::format_parse_context& ctx) {
// Simplified for this example, actually I want to implement a specific {:}
return ctx.begin();
}
auto format(std::string s, std::format_context& ctx) const {
for (char& c : s) {
c = std::toupper(static_cast<unsigned char>(c));
}
return std::format_to(ctx.out(), "{:s}", s);
}
};
int main() {
const std::string s = "hello world";
std::cout << std::format("{}", s) << "\n";
}
I expect the output HELLO WORLD, but the actual output is hello world.
You are not allowed to specialize std::formatter<std::string> because it does not rely on a program-defined type based on [namespace.std].
One workaround without providing std::formatter specialization is to transform the string-like object via views::transform and format it as a string, i.e., ":s":
constexpr auto to_upper =
std::views::transform(
[](char c) -> char { return std::toupper(static_cast<unsigned char>(c)); });
int main() {
const std::string s = "hello world";
std::cout << std::format("{:s}", to_upper(s)) << "\n";
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With