Fix operator| conflict with std::ranges (#1395)

This commit is contained in:
Roland Reichwein 2026-04-14 11:56:05 +02:00 committed by GitHub
parent 912e22f238
commit 3e4d41ca57
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 36 additions and 20 deletions

View File

@ -735,8 +735,23 @@ namespace etl
inline constexpr private_views::repeat repeat; inline constexpr private_views::repeat repeat;
} // namespace views } // namespace views
template <class Range> // Non-template base so ADL finds exactly one operator| definition.
class range_adapter_closure class range_adapter_closure_base
{
// Found via ADL on the RHS (any type that derives from
// range_adapter_closure_base). Placing the operator here instead of at
// global/namespace scope avoids conflicts with std::ranges::operator|.
template <class Range, class Closure,
typename = etl::enable_if_t< etl::is_base_of_v<range_adapter_closure_base, etl::decay_t<Closure>>
&& etl::is_invocable_v<etl::decay_t<Closure>, Range>>>
friend auto operator|(Range&& r, Closure&& c)
{
return etl::forward<Closure>(c)(etl::forward<Range>(r));
}
};
template <class Derived>
class range_adapter_closure : public range_adapter_closure_base
{ {
}; };
@ -932,7 +947,7 @@ namespace etl
{ {
namespace private_views namespace private_views
{ {
struct all struct all : public range_adapter_closure_base
{ {
template < class Range, template < class Range,
etl::enable_if_t<etl::is_base_of_v< etl::ranges::view_interface<etl::decay_t<Range>>, etl::decay_t<Range>>, int> = 0> etl::enable_if_t<etl::is_base_of_v< etl::ranges::view_interface<etl::decay_t<Range>>, etl::decay_t<Range>>, int> = 0>
@ -1422,7 +1437,7 @@ namespace etl
{ {
namespace private_views namespace private_views
{ {
struct as_rvalue struct as_rvalue : public range_adapter_closure_base
{ {
template <class Range> template <class Range>
constexpr auto operator()(Range&& r) const constexpr auto operator()(Range&& r) const
@ -1501,7 +1516,7 @@ namespace etl
{ {
namespace private_views namespace private_views
{ {
struct as_const struct as_const : public range_adapter_closure_base
{ {
template <class Range> template <class Range>
constexpr auto operator()(Range&& r) const constexpr auto operator()(Range&& r) const
@ -1726,7 +1741,7 @@ namespace etl
{ {
namespace private_views namespace private_views
{ {
struct cache_latest struct cache_latest : public range_adapter_closure_base
{ {
template <class Range> template <class Range>
constexpr auto operator()(Range&& r) const constexpr auto operator()(Range&& r) const
@ -1802,7 +1817,7 @@ namespace etl
{ {
namespace private_views namespace private_views
{ {
struct reverse struct reverse : public range_adapter_closure_base
{ {
template <class Range> template <class Range>
constexpr auto operator()(Range&& r) const constexpr auto operator()(Range&& r) const
@ -2397,7 +2412,7 @@ namespace etl
{ {
namespace private_views namespace private_views
{ {
struct join struct join : public range_adapter_closure_base
{ {
template <class Range> template <class Range>
constexpr auto operator()(Range&& r) const constexpr auto operator()(Range&& r) const
@ -4244,7 +4259,7 @@ namespace etl
{ {
namespace private_views namespace private_views
{ {
struct common struct common : public range_adapter_closure_base
{ {
template <class Range> template <class Range>
constexpr auto operator()(Range&& r) const constexpr auto operator()(Range&& r) const
@ -4404,7 +4419,7 @@ namespace etl
{ {
namespace private_views namespace private_views
{ {
struct enumerate struct enumerate : public range_adapter_closure_base
{ {
template <class Range> template <class Range>
constexpr auto operator()(Range&& r) const constexpr auto operator()(Range&& r) const
@ -4569,7 +4584,7 @@ namespace etl
namespace private_views namespace private_views
{ {
template <size_t N> template <size_t N>
struct elements_fn struct elements_fn : public range_adapter_closure_base
{ {
template <class Range> template <class Range>
constexpr auto operator()(Range&& r) const constexpr auto operator()(Range&& r) const
@ -4797,7 +4812,7 @@ namespace etl
namespace private_views namespace private_views
{ {
template <size_t N> template <size_t N>
struct adjacent_fn struct adjacent_fn : public range_adapter_closure_base
{ {
template <class Range> template <class Range>
constexpr auto operator()(Range&& r) const constexpr auto operator()(Range&& r) const
@ -6064,7 +6079,7 @@ namespace etl
{ {
namespace private_views namespace private_views
{ {
struct to_input struct to_input : public range_adapter_closure_base
{ {
template <class Range> template <class Range>
constexpr auto operator()(Range&& r) const constexpr auto operator()(Range&& r) const
@ -6152,13 +6167,6 @@ namespace etl
namespace views = ranges::views; namespace views = ranges::views;
} // namespace etl } // namespace etl
template < class Range, typename RangeAdaptorClosure, typename = etl::enable_if_t<etl::is_invocable_v<RangeAdaptorClosure, Range>>>
auto operator|(Range&& r, RangeAdaptorClosure rac)
{
return rac(etl::forward<Range>(r));
}
#endif #endif
#endif #endif

View File

@ -37,6 +37,14 @@ SOFTWARE.
#include <sstream> #include <sstream>
#include <vector> #include <vector>
// Issue #1391: include <ranges> when available to verify etl::operator|
// does not conflict with std::ranges::operator|.
#if ETL_USING_STL && ETL_USING_CPP20 && defined(__has_include)
#if __has_include(<ranges>)
#include <ranges>
#endif
#endif
#if ETL_USING_CPP17 #if ETL_USING_CPP17
// C++03 does not support move semantics as used in the ranges library // C++03 does not support move semantics as used in the ranges library