2

I was experimenting with C++20 ranges and I got the following strange behavior when compiling with GCC 11.1.0 and CMake 3.20.3. Specifically, the following code doesn't compile:

auto Foo() {
    std::vector<long int> x{1, 2, 3, 4, 5, 6};
    return std::views::all(x) | std::views::take(x.size());
    // return std::views::all(x) | std::views::take(static_cast<int>(x.size()));
}

resulting with very long error messages such as

[...] error: no match for ‘operator|’ (operand types are ‘std::ranges::ref_view<std::vector<long int> >’ and ‘std::ranges::views::__adaptor::_Partial<std::ranges::views::_Take, long unsigned int>’)
[build]   230 |     return std::views::all(x) | std::views::take(x.size());
[build]       |            ~~~~~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~
[build]       |                           |                     |
[build]       |                           |                     std::ranges::views::__adaptor::_Partial<std::ranges::views::_Take, long unsigned int>
[build]       |                           std::ranges::ref_view<std::vector<long int> >

and

[build] /usr/include/c++/11/ranges:739:13:   required for the satisfaction of ‘__adaptor_invocable<_Self, _Range>’ [with _Self = std::ranges::views::__adaptor::_Partial<std::ranges::views::_Take, long unsigned int>; _Range = std::ranges::ref_view<std::vector<long int, std::allocator<long int> > >]
[build] /usr/include/c++/11/ranges:740:9:   in requirements  [with _Args = {std::ranges::ref_view<std::vector<long int, std::allocator<long int> > >}; _Adaptor = std::ranges::views::__adaptor::_Partial<std::ranges::views::_Take, long unsigned int>]
[build] /usr/include/c++/11/ranges:740:44: note: the required expression ‘declval<_Adaptor>()((declval<_Args>)()...)’ is invalid, because
[build]   740 |       = requires { std::declval<_Adaptor>()(declval<_Args>()...); };
[build]       |                    ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~
[build] /usr/include/c++/11/ranges:740:44: error: use of deleted function ‘constexpr auto std::ranges::views::__adaptor::_Partial<_Adaptor, _Arg>::operator()(_Range&&) const && [with _Range = std::ranges::ref_view<std::vector<long int> >; _Adaptor = std::ranges::views::_Take; _Arg = long unsigned int]’
[build] /usr/include/c++/11/ranges:862:9: note: declared here
[build]   862 |         operator()(_Range&& __r) const && = delete;
[build]       |         ^~~~~~~~
[build] In file included from /usr/include/c++/11/streambuf:41,
[build]                  from /usr/include/c++/11/bits/streambuf_iterator.h:35,
[build]                  from /usr/include/c++/11/iterator:66,
[build]                  from /usr/include/c++/11/ranges:43,
[build]                  from ../mmpc/test/parametric_controller.test.cpp:27:
[build] /usr/include/c++/11/bits/ios_base.h:87:3: note: candidate: ‘constexpr std::_Ios_Fmtflags std::operator|(std::_Ios_Fmtflags, std::_Ios_Fmtflags)’
[build]    87 |   operator|(_Ios_Fmtflags __a, _Ios_Fmtflags __b)
[build]       |   ^~~~~~~~
[build] /usr/include/c++/11/bits/ios_base.h:87:27: note:   no known conversion for argument 1 from ‘std::ranges::ref_view<std::vector<long int> >’ to ‘std::_Ios_Fmtflags’
[build]    87 |   operator|(_Ios_Fmtflags __a, _Ios_Fmtflags __b)
[build]       |             ~~~~~~~~~~~~~~^~~
[build] /usr/include/c++/11/bits/ios_base.h:129:3: note: candidate: ‘constexpr std::_Ios_Openmode std::operator|(std::_Ios_Openmode, std::_Ios_Openmode)’
[build]   129 |   operator|(_Ios_Openmode __a, _Ios_Openmode __b)
[build]       |   ^~~~~~~~
[build] /usr/include/c++/11/bits/ios_base.h:129:27: note:   no known conversion for argument 1 from ‘std::ranges::ref_view<std::vector<long int> >’ to ‘std::_Ios_Openmode’
[build]   129 |   operator|(_Ios_Openmode __a, _Ios_Openmode __b)
[build]       |             ~~~~~~~~~~~~~~^~~
[build] /usr/include/c++/11/bits/ios_base.h:169:3: note: candidate: ‘constexpr std::_Ios_Iostate std::operator|(std::_Ios_Iostate, std::_Ios_Iostate)’
[build]   169 |   operator|(_Ios_Iostate __a, _Ios_Iostate __b)
[build]       |   ^~~~~~~~
[build] /usr/include/c++/11/bits/ios_base.h:169:26: note:   no known conversion for argument 1 from ‘std::ranges::ref_view<std::vector<long int> >’ to ‘std::_Ios_Iostate’
[build]   169 |   operator|(_Ios_Iostate __a, _Ios_Iostate __b)
[build]       |             ~~~~~~~~~~~~~^~~

However, when I convert the size of x to long int as in the commented line everything compiles fine. Is this behavior expected? Or is something wrong with my compiler setup?

Eventually, when I use Clang 12.0.1 nothing compiles at all and I get the following error:

[build] /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/ranges:3392:19: error: missing 'typename' prior to dependent type name 'iterator_traits<iterator_t<_Base>>::iterator_category'
[build]             using _Cat = iterator_traits<iterator_t<_Base>>::iterator_category;
[build]                          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Shouldn't Clang 12.0.1 support the features of C++20 including ranges? Why do I get this error?

1 Answer 1

8

This is a library bug that will be fixed by P2367, since this is specified to do take_view{E, F} (which would be a narrowing conversion) instead of just take_view(E, F) (which would be fine). In the meantime, you have to do the cast accordingly.


Also this:

std::views::all(x) | std::views::take(x.size());

is just a long way of writing:

x | std::views::take(x.size());

You should rarely (if ever?) need to write views::all in user code. The library does this for you.


Shouldn't Clang 12.0.1 support the features of C++20 including ranges? Why do I get this error?

This has nothing to do with ranges, clang just doesn't fully support the C++20 language features that libstdc++ uses in its implementation (in this case Down with typename!).

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you very much for your answer! Also, I used std::views::all just for testing purposes, but I know it's unnecessary! May I just ask you if there's a workaround to use Clang with C++20 ranges, like some patches or third-party updates?
@fdev Nope. You could use range-v3 instead.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.