mirror of
https://github.com/fmtlib/fmt.git
synced 2026-04-30 19:09:22 +08:00
Fix compile time format for ranges, style, and std
This commit is contained in:
parent
eeff8680ed
commit
be3ae4ed5d
@ -471,7 +471,7 @@ template <typename Char> inline void reset_color(buffer<Char>& buffer) {
|
||||
template <typename T> struct styled_arg : view {
|
||||
const T& value;
|
||||
text_style style;
|
||||
styled_arg(const T& v, text_style s) : value(v), style(s) {}
|
||||
FMT_CONSTEXPR styled_arg(const T& v, text_style s) : value(v), style(s) {}
|
||||
};
|
||||
|
||||
template <typename Char>
|
||||
@ -583,8 +583,8 @@ inline auto format_to(OutputIt out, text_style ts, format_string<T...> fmt,
|
||||
template <typename T, typename Char>
|
||||
struct formatter<detail::styled_arg<T>, Char> : formatter<T, Char> {
|
||||
template <typename FormatContext>
|
||||
auto format(const detail::styled_arg<T>& arg, FormatContext& ctx) const
|
||||
-> decltype(ctx.out()) {
|
||||
FMT_CONSTEXPR auto format(const detail::styled_arg<T>& arg,
|
||||
FormatContext& ctx) const -> decltype(ctx.out()) {
|
||||
const auto& ts = arg.style;
|
||||
auto out = ctx.out();
|
||||
|
||||
|
||||
@ -3888,7 +3888,7 @@ template <typename OutputIt, typename Char> class generic_context {
|
||||
|
||||
constexpr auto out() const -> iterator { return out_; }
|
||||
|
||||
void advance_to(iterator it) {
|
||||
constexpr void advance_to(iterator it) {
|
||||
if (!detail::is_back_insert_iterator<iterator>()) out_ = it;
|
||||
}
|
||||
|
||||
|
||||
@ -69,11 +69,12 @@ struct has_member_fn_begin_end_t<T, void_t<decltype(*std::declval<T>().begin()),
|
||||
|
||||
// Member function overloads.
|
||||
template <typename T>
|
||||
auto range_begin(T&& rng) -> decltype(static_cast<T&&>(rng).begin()) {
|
||||
FMT_CONSTEXPR auto range_begin(T&& rng)
|
||||
-> decltype(static_cast<T&&>(rng).begin()) {
|
||||
return static_cast<T&&>(rng).begin();
|
||||
}
|
||||
template <typename T>
|
||||
auto range_end(T&& rng) -> decltype(static_cast<T&&>(rng).end()) {
|
||||
FMT_CONSTEXPR auto range_end(T&& rng) -> decltype(static_cast<T&&>(rng).end()) {
|
||||
return static_cast<T&&>(rng).end();
|
||||
}
|
||||
|
||||
@ -460,7 +461,8 @@ struct range_formatter<
|
||||
}
|
||||
|
||||
template <typename R, typename FormatContext>
|
||||
auto format(R&& range, FormatContext& ctx) const -> decltype(ctx.out()) {
|
||||
FMT_CONSTEXPR auto format(R&& range, FormatContext& ctx) const
|
||||
-> decltype(ctx.out()) {
|
||||
auto out = ctx.out();
|
||||
auto it = detail::range_begin(range);
|
||||
auto end = detail::range_end(range);
|
||||
@ -516,7 +518,7 @@ struct formatter<
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
auto format(range_type& range, FormatContext& ctx) const
|
||||
FMT_CONSTEXPR auto format(range_type& range, FormatContext& ctx) const
|
||||
-> decltype(ctx.out()) {
|
||||
return range_formatter_.format(range, ctx);
|
||||
}
|
||||
@ -625,7 +627,7 @@ struct join_view : detail::view {
|
||||
Sentinel end;
|
||||
basic_string_view<Char> sep;
|
||||
|
||||
join_view(It b, Sentinel e, basic_string_view<Char> s)
|
||||
FMT_CONSTEXPR join_view(It b, Sentinel e, basic_string_view<Char> s)
|
||||
: begin(std::move(b)), end(e), sep(s) {}
|
||||
};
|
||||
|
||||
@ -652,7 +654,8 @@ struct formatter<join_view<It, Sentinel, Char>, Char> {
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
auto format(view& value, FormatContext& ctx) const -> decltype(ctx.out()) {
|
||||
FMT_CONSTEXPR auto format(view& value, FormatContext& ctx) const
|
||||
-> decltype(ctx.out()) {
|
||||
using iter =
|
||||
conditional_t<std::is_copy_constructible<view>::value, It, It&>;
|
||||
iter it = value.begin;
|
||||
@ -675,7 +678,7 @@ template <typename Tuple, typename Char> struct tuple_join_view : detail::view {
|
||||
const Tuple& tuple;
|
||||
basic_string_view<Char> sep;
|
||||
|
||||
tuple_join_view(const Tuple& t, basic_string_view<Char> s)
|
||||
FMT_CONSTEXPR tuple_join_view(const Tuple& t, basic_string_view<Char> s)
|
||||
: tuple(t), sep{s} {}
|
||||
};
|
||||
|
||||
@ -694,8 +697,9 @@ struct formatter<tuple_join_view<Tuple, Char>, Char,
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
auto format(const tuple_join_view<Tuple, Char>& value,
|
||||
FormatContext& ctx) const -> typename FormatContext::iterator {
|
||||
FMT_CONSTEXPR auto format(const tuple_join_view<Tuple, Char>& value,
|
||||
FormatContext& ctx) const ->
|
||||
typename FormatContext::iterator {
|
||||
return do_format(value, ctx, std::tuple_size<Tuple>());
|
||||
}
|
||||
|
||||
@ -726,15 +730,17 @@ struct formatter<tuple_join_view<Tuple, Char>, Char,
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
auto do_format(const tuple_join_view<Tuple, Char>&, FormatContext& ctx,
|
||||
std::integral_constant<size_t, 0>) const ->
|
||||
FMT_CONSTEXPR auto do_format(const tuple_join_view<Tuple, Char>&,
|
||||
FormatContext& ctx,
|
||||
std::integral_constant<size_t, 0>) const ->
|
||||
typename FormatContext::iterator {
|
||||
return ctx.out();
|
||||
}
|
||||
|
||||
template <typename FormatContext, size_t N>
|
||||
auto do_format(const tuple_join_view<Tuple, Char>& value, FormatContext& ctx,
|
||||
std::integral_constant<size_t, N>) const ->
|
||||
FMT_CONSTEXPR auto do_format(const tuple_join_view<Tuple, Char>& value,
|
||||
FormatContext& ctx,
|
||||
std::integral_constant<size_t, N>) const ->
|
||||
typename FormatContext::iterator {
|
||||
using std::get;
|
||||
auto out =
|
||||
@ -813,7 +819,7 @@ auto join(It begin, Sentinel end, string_view sep) -> join_view<It, Sentinel> {
|
||||
* // Output: 01, 02, 03
|
||||
*/
|
||||
template <typename Range, FMT_ENABLE_IF(!is_tuple_like<Range>::value)>
|
||||
auto join(Range&& r, string_view sep)
|
||||
FMT_CONSTEXPR auto join(Range&& r, string_view sep)
|
||||
-> join_view<decltype(detail::range_begin(r)),
|
||||
decltype(detail::range_end(r))> {
|
||||
return {detail::range_begin(r), detail::range_end(r), sep};
|
||||
|
||||
@ -133,8 +133,8 @@ void write_escaped_path(basic_memory_buffer<Char>& quoted,
|
||||
#if defined(__cpp_lib_expected) || FMT_CPP_LIB_VARIANT
|
||||
|
||||
template <typename Char, typename OutputIt, typename T, typename FormatContext>
|
||||
auto write_escaped_alternative(OutputIt out, const T& v, FormatContext& ctx)
|
||||
-> OutputIt {
|
||||
FMT_CONSTEXPR auto write_escaped_alternative(OutputIt out, const T& v,
|
||||
FormatContext& ctx) -> OutputIt {
|
||||
if constexpr (has_to_string_view<T>::value)
|
||||
return write_escaped_string<Char>(out, detail::to_string_view(v));
|
||||
if constexpr (std::is_same_v<T, Char>) return write_escaped_char(out, v);
|
||||
@ -508,7 +508,7 @@ template <typename Char> struct formatter<std::monostate, Char> {
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
auto format(const std::monostate&, FormatContext& ctx) const
|
||||
FMT_CONSTEXPR auto format(const std::monostate&, FormatContext& ctx) const
|
||||
-> decltype(ctx.out()) {
|
||||
return detail::write<Char>(ctx.out(), "monostate");
|
||||
}
|
||||
@ -524,7 +524,7 @@ struct formatter<Variant, Char,
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
auto format(const Variant& value, FormatContext& ctx) const
|
||||
FMT_CONSTEXPR20 auto format(const Variant& value, FormatContext& ctx) const
|
||||
-> decltype(ctx.out()) {
|
||||
auto out = ctx.out();
|
||||
|
||||
@ -635,7 +635,7 @@ struct formatter<
|
||||
}
|
||||
|
||||
template <typename Context>
|
||||
auto format(const std::exception& ex, Context& ctx) const
|
||||
FMT_CONSTEXPR auto format(const std::exception& ex, Context& ctx) const
|
||||
-> decltype(ctx.out()) {
|
||||
auto out = ctx.out();
|
||||
#if FMT_USE_RTTI
|
||||
@ -690,11 +690,12 @@ struct formatter<BitRef, Char,
|
||||
#ifdef __cpp_lib_byte
|
||||
template <typename Char>
|
||||
struct formatter<std::byte, Char> : formatter<unsigned, Char> {
|
||||
static auto format_as(std::byte b) -> unsigned char {
|
||||
FMT_CONSTEXPR static auto format_as(std::byte b) -> unsigned char {
|
||||
return static_cast<unsigned char>(b);
|
||||
}
|
||||
template <typename Context>
|
||||
auto format(std::byte b, Context& ctx) const -> decltype(ctx.out()) {
|
||||
FMT_CONSTEXPR auto format(std::byte b, Context& ctx) const
|
||||
-> decltype(ctx.out()) {
|
||||
return formatter<unsigned, Char>::format(format_as(b), ctx);
|
||||
}
|
||||
};
|
||||
|
||||
@ -13,7 +13,9 @@
|
||||
#include <vector>
|
||||
|
||||
#include "fmt/chrono.h"
|
||||
#include "fmt/color.h"
|
||||
#include "fmt/ranges.h"
|
||||
#include "fmt/std.h"
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest-extra.h"
|
||||
|
||||
@ -87,7 +89,6 @@ TEST(compile_test, format_escape) {
|
||||
EXPECT_EQ("\"abc\" ", fmt::format(FMT_COMPILE("{0:<7?}"), "abc"));
|
||||
}
|
||||
|
||||
|
||||
TEST(compile_test, format_specs) {
|
||||
EXPECT_EQ("42", fmt::format(FMT_COMPILE("{:x}"), 0x42));
|
||||
EXPECT_EQ("1.2 ms ",
|
||||
@ -224,6 +225,19 @@ TEST(compile_test, constexpr_formatted_size) {
|
||||
FMT_CONSTEXPR20 size_t str_size =
|
||||
fmt::formatted_size(FMT_COMPILE("{:s}"), "abc");
|
||||
EXPECT_EQ(str_size, 3);
|
||||
FMT_CONSTEXPR20 size_t tuple_size = fmt::formatted_size(
|
||||
FMT_COMPILE("{}"), fmt::join(std::tuple(1, 2, 3), ","));
|
||||
EXPECT_EQ(tuple_size, 5);
|
||||
FMT_CONSTEXPR20 size_t array_size = fmt::formatted_size(
|
||||
FMT_COMPILE("{}"), fmt::join(std::array{1, 2, 3}, ","));
|
||||
EXPECT_EQ(array_size, 5);
|
||||
FMT_CONSTEXPR20 size_t styled_size = fmt::formatted_size(
|
||||
FMT_COMPILE("{}"),
|
||||
fmt::styled(std::array{1, 2, 3}, fmt::bg(fmt::color::green)));
|
||||
EXPECT_EQ(styled_size, 32);
|
||||
FMT_CONSTEXPR20 size_t variant_size = fmt::formatted_size(
|
||||
FMT_COMPILE("{}"), std::variant<std::monostate, char>{});
|
||||
EXPECT_EQ(variant_size, 18);
|
||||
}
|
||||
|
||||
TEST(compile_test, static_format) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user