Skip to content

Commit

Permalink
Extending fmt::join to support C++20-only ranges. (fmtlib#2549)
Browse files Browse the repository at this point in the history
  • Loading branch information
brevzin authored and PoetaKodu committed Nov 11, 2021
1 parent 10b6e1b commit d957c7e
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 3 deletions.
13 changes: 10 additions & 3 deletions include/fmt/format.h
Original file line number Diff line number Diff line change
Expand Up @@ -2748,7 +2748,12 @@ using arg_join FMT_DEPRECATED_ALIAS = join_view<It, Sentinel, Char>;
template <typename It, typename Sentinel, typename Char>
struct formatter<join_view<It, Sentinel, Char>, Char> {
private:
using value_type = typename std::iterator_traits<It>::value_type;
using value_type =
#ifdef __cpp_lib_ranges
std::iter_value_t<It>;
#else
typename std::iterator_traits<It>::value_type;
#endif
using context = buffer_context<Char>;
using mapper = detail::arg_mapper<context>;

Expand Down Expand Up @@ -2782,11 +2787,13 @@ struct formatter<join_view<It, Sentinel, Char>, Char> {
auto it = value.begin;
auto out = ctx.out();
if (it != value.end) {
out = value_formatter_.format(map(*it++), ctx);
out = value_formatter_.format(map(*it), ctx);
++it;
while (it != value.end) {
out = detail::copy_str<Char>(value.sep.begin(), value.sep.end(), out);
ctx.advance_to(out);
out = value_formatter_.format(map(*it++), ctx);
out = value_formatter_.format(map(*it), ctx);
++it;
}
}
return out;
Expand Down
38 changes: 38 additions & 0 deletions test/ranges-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,36 @@ struct zstring {
zstring_sentinel end() const { return {}; }
};

# ifdef __cpp_lib_ranges
struct cpp20_only_range {
struct iterator {
int val = 0;

using value_type = int;
using difference_type = std::ptrdiff_t;
using iterator_concept = std::input_iterator_tag;

iterator() = default;
iterator(int i) : val(i) {}
int operator*() const { return val; }
iterator& operator++() {
++val;
return *this;
}
void operator++(int) { ++*this; }
bool operator==(const iterator& rhs) const { return val == rhs.val; }
};

int lo;
int hi;

iterator begin() const { return iterator(lo); }
iterator end() const { return iterator(hi); }
};

static_assert(std::input_iterator<cpp20_only_range::iterator>);
# endif

TEST(ranges_test, join_sentinel) {
auto hello = zstring{"hello"};
EXPECT_EQ(fmt::format("{}", hello), "['h', 'e', 'l', 'l', 'o']");
Expand All @@ -282,6 +312,14 @@ TEST(ranges_test, join_range) {

const auto z = std::vector<int>(3u, 0);
EXPECT_EQ(fmt::format("{}", fmt::join(z, ",")), "0,0,0");

# ifdef __cpp_lib_ranges
EXPECT_EQ(fmt::format("{}", cpp20_only_range{.lo = 0, .hi = 5}),
"[0, 1, 2, 3, 4]");
EXPECT_EQ(
fmt::format("{}", fmt::join(cpp20_only_range{.lo = 0, .hi = 5}, ",")),
"0,1,2,3,4");
# endif
}
#endif // FMT_RANGES_TEST_ENABLE_JOIN

Expand Down

0 comments on commit d957c7e

Please sign in to comment.