ericniebler / range-v3

Range library for C++14/17/20, basis for C++20's std::ranges
Other
4.12k stars 441 forks source link

gcc10 --std=c++2a: range-v3 views are not combinable with std::views #1470

Open marehr opened 4 years ago

marehr commented 4 years ago

https://godbolt.org/z/6_BQS3

#include <ranges>
#include <string>
#include <range/v3/view/take.hpp>

int main()
{
    std::string str{"foo"};

    auto v3 = str | std::views::take(5) | ranges::view::take(1);
    return 0;
}

with g++10 --std=c++2a

will result in

<source>: In function 'int main()':
<source>:9:63: error: use of deleted function 'constexpr concepts::return_t<Rng, typename std::enable_if<((range<Rng> && (! viewable_range<Rng>)) && concepts::detail::CPP_true(concepts::detail::Nil{})), void>::type> ranges::views::view_closure_base_ns::operator|(Rng&&, const ranges::views::view_closure<ViewFn>&) [with Rng = std::ranges::take_view<std::ranges::ref_view<std::__cxx11::basic_string<char> > >; ViewFn = ranges::detail::bind_back_fn_<ranges::views::take_base_fn, int>; concepts::return_t<Rng, typename std::enable_if<((range<Rng> && (! viewable_range<Rng>)) && concepts::detail::CPP_true(concepts::detail::Nil{})), void>::type> = std::ranges::take_view<std::ranges::ref_view<std::__cxx11::basic_string<char> > >; typename std::enable_if<((range<Rng> && (! viewable_range<Rng>)) && concepts::detail::CPP_true(concepts::detail::Nil{})), void>::type = void]'
    9 |     auto v3 = str | std::views::take(5) | ranges::view::take(1);
      |                                                               ^
In file included from /opt/compiler-explorer/libs/rangesv3/trunk/include/range/v3/view/all.hpp:28,
                 from /opt/compiler-explorer/libs/rangesv3/trunk/include/range/v3/view/take.hpp:28,
                 from <source>:3:
/opt/compiler-explorer/libs/rangesv3/trunk/include/range/v3/view/view.hpp:127:13: note: declared here
  127 |             operator|(Rng &&, view_closure<ViewFn> const &) // ******* READ THIS ********
      |             ^~~~~~~~

looking at

https://github.com/ericniebler/range-v3/blob/1334a702e680dd407d53edc6230ee489d07a9186/include/range/v3/view/view.hpp#L122-L139

says something that I don't understand :)

marehr commented 4 years ago

Okay I figured it out, the problem is that ranges::view_ does not know that std::ranges::view_base is the "right" view base.

https://eel.is/c++draft/range.view#4

Comparing (std)::ranges::viewable_range showed that both concepts use a different definition (https://godbolt.org/z/yF9JWq).

So fixing that with

#include <ranges>
#include <string>
#include <range/v3/view/take.hpp>

namespace ranges
{
// std::ranges::views are valid range-v3 views
template<class T>
    requires std::derived_from<T, std::ranges::view_base>
inline constexpr bool enable_view<T> = true;
} // namespace ranges

namespace std::ranges
{
// range-v3 views are valid std::ranges::views
template<class T>
    requires std::derived_from<T, ::ranges::view_base>
inline constexpr bool enable_view<T> = true;
} // namespace std::ranges

int main()
{
    std::string str{"foo"};

    auto v3 = str | std::views::take(5) | ranges::view::take(1);
    return 0;
}

https://godbolt.org/z/a_zmyu