Consider ADL begin() and end() when joining ranges (#3824)

Closes #3813

Signed-off-by: Beat Bolli <dev@drbeat.li>
This commit is contained in:
Beat Bolli 2024-01-22 16:39:33 +01:00 committed by GitHub
parent 2caf1b3b91
commit e1832bcf00
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 35 additions and 2 deletions

View File

@ -578,6 +578,22 @@ auto join(It begin, Sentinel end, string_view sep) -> join_view<It, Sentinel> {
return {begin, end, sep};
}
namespace detail {
// ADL helpers for fmt::join()
namespace adl {
using std::begin;
using std::end;
template <typename Range> auto adlbegin(Range& r) -> decltype(begin(r)) {
return begin(r);
}
template <typename Range> auto adlend(Range& r) -> decltype(end(r)) {
return end(r);
}
} // namespace adl
} // namespace detail
/**
\rst
Returns a view that formats `range` with elements separated by `sep`.
@ -596,8 +612,9 @@ auto join(It begin, Sentinel end, string_view sep) -> join_view<It, Sentinel> {
*/
template <typename Range>
auto join(Range&& range, string_view sep)
-> join_view<decltype(std::begin(range)), decltype(std::end(range))> {
return join(std::begin(range), std::end(range), sep);
-> join_view<decltype(detail::adl::adlbegin(range)),
decltype(detail::adl::adlend(range))> {
return join(detail::adl::adlbegin(range), detail::adl::adlend(range), sep);
}
template <typename Char, typename... T> struct tuple_join_view : detail::view {

View File

@ -455,6 +455,22 @@ TEST(ranges_test, join_range) {
"0,1,2,3,4");
# endif
}
namespace adl {
struct vec : std::vector<int> {
using std::vector<int>::vector; // inherit all constructors
};
// ADL-found begin() and end() skip the first and last element
auto begin(vec& v) -> typename vec::iterator { return v.begin() + 1; }
auto end(vec& v) -> typename vec::iterator { return v.end() - 1; }
}
TEST(ranges_test, format_join_adl_begin_end) {
auto v = adl::vec{41, 42, 43, 44};
EXPECT_EQ(fmt::format("{}", fmt::join(v, "/")), "42/43");
}
#endif // FMT_RANGES_TEST_ENABLE_JOIN
#if defined(__cpp_lib_ranges) && __cpp_lib_ranges >= 202302L