Skip to content

Commit

Permalink
Add a set formatter
Browse files Browse the repository at this point in the history
  • Loading branch information
vitaut committed Dec 18, 2021
1 parent 121002d commit c882790
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 25 deletions.
55 changes: 30 additions & 25 deletions include/fmt/ranges.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,6 @@

FMT_BEGIN_NAMESPACE

template <typename Char, typename Enable = void> struct formatting_range {
#ifdef FMT_DEPRECATED_BRACED_RANGES
Char prefix = '{';
Char postfix = '}';
#else
Char prefix = '[';
Char postfix = ']';
#endif

template <typename ParseContext>
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
return ctx.begin();
}
};

template <typename Char, typename Enable = void> struct formatting_tuple {
Char prefix = '(';
Char postfix = ')';
Expand Down Expand Up @@ -87,7 +72,7 @@ template <typename Char>
struct is_std_string_like<fmt::basic_string_view<Char>> : std::true_type {};

template <typename T> class is_map {
template <typename U> static auto check(U*) -> typename U::key_type;
template <typename U> static auto check(U*) -> typename U::mapped_type;
template <typename> static void check(...);

public:
Expand All @@ -99,6 +84,19 @@ template <typename T> class is_map {
#endif
};

template <typename T> class is_set {
template <typename U> static auto check(U*) -> typename U::key_type;
template <typename> static void check(...);

public:
#ifdef FMT_FORMAT_SET_AS_LIST
static FMT_CONSTEXPR_DECL const bool value = false;
#else
static FMT_CONSTEXPR_DECL const bool value =
!std::is_void<decltype(check<T>(nullptr))>::value && !is_map<T>::value;
#endif
};

template <typename... Ts> struct conditional_helper {};

template <typename T, typename _ = void> struct is_range_ : std::false_type {};
Expand Down Expand Up @@ -602,29 +600,36 @@ struct formatter<
detail::has_fallback_formatter<detail::value_type<T>, Char>::value)
#endif
>> {
formatting_range<Char> formatting;

template <typename ParseContext>
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
return formatting.parse(ctx);
return ctx.begin();
}

template <
typename FormatContext, typename U,
FMT_ENABLE_IF(
std::is_same<U, conditional_t<detail::has_const_begin_end<T>::value,
const T, T>>::value)>
auto format(U& values, FormatContext& ctx) -> decltype(ctx.out()) {
auto out = detail::copy(formatting.prefix, ctx.out());
size_t i = 0;
auto it = std::begin(values);
auto end = std::end(values);
auto format(U& range, FormatContext& ctx) -> decltype(ctx.out()) {
#ifdef FMT_DEPRECATED_BRACED_RANGES
Char prefix = '{';
Char postfix = '}';
#else
Char prefix = detail::is_set<T>::value ? '{' : '[';
Char postfix = detail::is_set<T>::value ? '}' : ']';
#endif
auto out = ctx.out();
*out++ = prefix;
int i = 0;
auto it = std::begin(range);
auto end = std::end(range);
for (; it != end; ++it) {
if (i > 0) out = detail::write_delimiter(out);
out = detail::write_range_entry<Char>(out, *it);
++i;
}
return detail::copy(formatting.postfix, out);
*out++ = postfix;
return out;
}
};

Expand Down
5 changes: 5 additions & 0 deletions test/ranges-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ TEST(ranges_test, format_map) {
EXPECT_EQ(fmt::format("{}", m), "{\"one\": 1, \"two\": 2}");
}

TEST(ranges_test, format_set) {
EXPECT_EQ(fmt::format("{}", std::set<std::string>{"one", "two"}),
"{\"one\", \"two\"}");
}

TEST(ranges_test, format_pair) {
auto p = std::pair<int, float>(42, 1.5f);
EXPECT_EQ(fmt::format("{}", p), "(42, 1.5)");
Expand Down

0 comments on commit c882790

Please sign in to comment.