mirror of
https://github.com/fmtlib/fmt.git
synced 2025-08-02 12:14:43 +02:00
Dedup ADL begin/end lookup
This commit is contained in:
@@ -69,13 +69,13 @@ struct has_member_fn_begin_end_t<T, void_t<decltype(std::declval<T>().begin()),
|
|||||||
decltype(std::declval<T>().end())>>
|
decltype(std::declval<T>().end())>>
|
||||||
: std::true_type {};
|
: std::true_type {};
|
||||||
|
|
||||||
// Member function overload
|
// Member function overloads.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
auto range_begin(T&& rng) FMT_DECLTYPE_RETURN(static_cast<T&&>(rng).begin());
|
auto range_begin(T&& rng) FMT_DECLTYPE_RETURN(static_cast<T&&>(rng).begin());
|
||||||
template <typename T>
|
template <typename T>
|
||||||
auto range_end(T&& rng) FMT_DECLTYPE_RETURN(static_cast<T&&>(rng).end());
|
auto range_end(T&& rng) FMT_DECLTYPE_RETURN(static_cast<T&&>(rng).end());
|
||||||
|
|
||||||
// ADL overload. Only participates in overload resolution if member functions
|
// ADL overloads. Only participate in overload resolution if member functions
|
||||||
// are not found.
|
// are not found.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
auto range_begin(T&& rng)
|
auto range_begin(T&& rng)
|
||||||
@@ -619,22 +619,6 @@ auto join(It begin, Sentinel end, string_view sep) -> join_view<It, Sentinel> {
|
|||||||
return {begin, end, sep};
|
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
|
\rst
|
||||||
Returns a view that formats `range` with elements separated by `sep`.
|
Returns a view that formats `range` with elements separated by `sep`.
|
||||||
@@ -652,10 +636,10 @@ template <typename Range> auto adlend(Range& r) -> decltype(end(r)) {
|
|||||||
\endrst
|
\endrst
|
||||||
*/
|
*/
|
||||||
template <typename Range>
|
template <typename Range>
|
||||||
auto join(Range&& range, string_view sep)
|
auto join(Range&& r, string_view sep)
|
||||||
-> join_view<decltype(detail::adl::adlbegin(range)),
|
-> join_view<decltype(detail::range_begin(r)),
|
||||||
decltype(detail::adl::adlend(range))> {
|
decltype(detail::range_end(r))> {
|
||||||
return join(detail::adl::adlbegin(range), detail::adl::adlend(range), sep);
|
return {detail::range_begin(r), detail::range_end(r), sep};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char, typename... T> struct tuple_join_view : detail::view {
|
template <typename Char, typename... T> struct tuple_join_view : detail::view {
|
||||||
|
@@ -462,18 +462,16 @@ TEST(ranges_test, join_range) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace adl {
|
namespace adl {
|
||||||
struct vec : std::vector<int> {
|
struct vec {
|
||||||
using std::vector<int>::vector; // inherit all constructors
|
int n[2] = {42, 43};
|
||||||
};
|
};
|
||||||
|
|
||||||
// ADL-found begin() and end() skip the first and last element
|
auto begin(const vec& v) -> const int* { return v.n; }
|
||||||
auto begin(vec& v) -> typename vec::iterator { return v.begin() + 1; }
|
auto end(const vec& v) -> const int* { return v.n + 2; }
|
||||||
auto end(vec& v) -> typename vec::iterator { return v.end() - 1; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ranges_test, format_join_adl_begin_end) {
|
TEST(ranges_test, format_join_adl_begin_end) {
|
||||||
auto v = adl::vec{41, 42, 43, 44};
|
EXPECT_EQ(fmt::format("{}", fmt::join(adl::vec(), "/")), "42/43");
|
||||||
EXPECT_EQ(fmt::format("{}", fmt::join(v, "/")), "42/43");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // FMT_RANGES_TEST_ENABLE_JOIN
|
#endif // FMT_RANGES_TEST_ENABLE_JOIN
|
||||||
|
Reference in New Issue
Block a user