Skip to content

Commit

Permalink
Simplify join_view formatter
Browse files Browse the repository at this point in the history
  • Loading branch information
vitaut committed May 8, 2024
1 parent 328d256 commit d2473b7
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 46 deletions.
38 changes: 13 additions & 25 deletions include/fmt/ranges.h
Original file line number Diff line number Diff line change
Expand Up @@ -623,41 +623,29 @@ struct formatter<join_view<It, Sentinel, Char>, Char> {
#endif
formatter<remove_cvref_t<value_type>, Char> value_formatter_;

using view_ref = conditional_t<std::is_copy_constructible<It>::value,
const join_view<It, Sentinel, Char>&,
join_view<It, Sentinel, Char>&&>;

public:
template <typename ParseContext>
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> const Char* {
return value_formatter_.parse(ctx);
}

template <typename FormatContext, typename Iter,
FMT_ENABLE_IF(std::is_copy_constructible<Iter>::value)>
auto format(const join_view<Iter, Sentinel, Char>& value,
FormatContext& ctx) const -> decltype(ctx.out()) {
auto it = value.begin;
return do_format(value, ctx, it);
}

template <typename FormatContext, typename Iter,
FMT_ENABLE_IF(!std::is_copy_constructible<Iter>::value)>
auto format(join_view<Iter, Sentinel, Char>& value, FormatContext& ctx) const
-> decltype(ctx.out()) {
return do_format(value, ctx, value.begin);
}

private:
template <typename FormatContext>
auto do_format(const join_view<It, Sentinel, Char>& value, FormatContext& ctx,
It& it) const -> decltype(ctx.out()) {
auto format(view_ref& value, FormatContext& ctx) const
-> decltype(ctx.out()) {
auto it = std::forward<view_ref>(value).begin;
auto out = ctx.out();
if (it != value.end) {
if (it == value.end) return out;
out = value_formatter_.format(*it, ctx);
++it;
while (it != value.end) {
out = detail::copy<Char>(value.sep.begin(), value.sep.end(), out);
ctx.advance_to(out);
out = value_formatter_.format(*it, ctx);
++it;
while (it != value.end) {
out = detail::copy<Char>(value.sep.begin(), value.sep.end(), out);
ctx.advance_to(out);
out = value_formatter_.format(*it, ctx);
++it;
}
}
return out;
}
Expand Down
42 changes: 21 additions & 21 deletions test/ranges-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -667,41 +667,41 @@ TEST(ranges_test, lvalue_qualified_begin_end) {

#if ENABLE_INPUT_RANGE_JOIN_TEST
TEST(ranges_test, input_range_join) {
std::istringstream iss("1 2 3 4 5");
auto iss = std::istringstream("1 2 3 4 5");
auto view = std::views::istream<std::string>(iss);
auto joined_view = fmt::join(view.begin(), view.end(), ", ");
EXPECT_EQ("1, 2, 3, 4, 5", fmt::format("{}", std::move(joined_view)));
EXPECT_EQ("1, 2, 3, 4, 5",
fmt::format("{}", fmt::join(view.begin(), view.end(), ", ")));
}

TEST(ranges_test, input_range_join_overload) {
std::istringstream iss("1 2 3 4 5");
auto iss = std::istringstream("1 2 3 4 5");
EXPECT_EQ(
"1.2.3.4.5",
fmt::format("{}", fmt::join(std::views::istream<std::string>(iss), ".")));
}
#endif

TEST(ranges_test, std_istream_iterator_join) {
std::istringstream iss("1 2 3 4 5");
std::istream_iterator<int> first{iss};
std::istream_iterator<int> last{};
auto joined_view = fmt::join(first, last, ", ");
EXPECT_EQ("1, 2, 3, 4, 5", fmt::format("{}", std::move(joined_view)));
auto&& iss = std::istringstream("1 2 3 4 5");
auto first = std::istream_iterator<int>(iss);
auto last = std::istream_iterator<int>();
EXPECT_EQ("1, 2, 3, 4, 5", fmt::format("{}", fmt::join(first, last, ", ")));
}

TEST(ranges_test, movable_only_istream_iter_join) {
// Mirrors c++20 std::ranges::basic_istream_view::iterator
struct UncopyableIstreamIter : std::istream_iterator<int> {
explicit UncopyableIstreamIter(std::istringstream& iss)
// Mirrors C++20 std::ranges::basic_istream_view::iterator.
struct noncopyable_istream_iterator : std::istream_iterator<int> {
explicit noncopyable_istream_iterator(std::istringstream& iss)
: std::istream_iterator<int>{iss} {}
UncopyableIstreamIter(const UncopyableIstreamIter&) = delete;
UncopyableIstreamIter(UncopyableIstreamIter&&) = default;
noncopyable_istream_iterator(const noncopyable_istream_iterator&) = delete;
noncopyable_istream_iterator(noncopyable_istream_iterator&&) = default;
};
static_assert(!std::is_copy_constructible<UncopyableIstreamIter>::value, "");

std::istringstream iss("1 2 3 4 5");
UncopyableIstreamIter first{iss};
std::istream_iterator<int> last{};
auto joined_view = fmt::join(std::move(first), last, ", ");
EXPECT_EQ("1, 2, 3, 4, 5", fmt::format("{}", std::move(joined_view)));
static_assert(
!std::is_copy_constructible<noncopyable_istream_iterator>::value, "");

auto&& iss = std::istringstream("1 2 3 4 5");
auto first = noncopyable_istream_iterator(iss);
auto last = std::istream_iterator<int>();
EXPECT_EQ("1, 2, 3, 4, 5",
fmt::format("{}", fmt::join(std::move(first), last, ", ")));
}

0 comments on commit d2473b7

Please sign in to comment.