C++20 范围和 std::views::take 错误
Error with C++20 ranges and std::views::take
我正在试验 C++20 范围,在使用 GCC 11.1.0 和 CMake 3.20.3 进行编译时出现以下奇怪行为。具体来说,以下代码无法编译:
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()));
}
导致非常长的错误消息,例如
[...] 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> >
和
[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] | ~~~~~~~~~~~~~^~~
但是,当我将 x
的大小转换为 long int
时,如注释行中所示,一切都可以正常编译。 这种行为是预期的吗?还是我的编译器设置有问题?
最终,当我使用 Clang 12.0.1 时,根本无法编译任何内容,并且出现以下错误:
[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] ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Clang 12.0.1 不应该支持 C++20 的特性,包括范围吗?为什么会出现此错误?
这是一个库错误,将由 P2367 修复,因为它被指定用于 take_view{E, F}
(这将是一个收缩转换)而不只是 take_view(E, F)
(这会很好)。与此同时,你必须相应地进行转换。
还有这个:
std::views::all(x) | std::views::take(x.size());
只是写的很长:
x | std::views::take(x.size());
您应该很少(如果有的话?)需要在用户代码中编写 views::all
。图书馆为您做这件事。
Shouldn't Clang 12.0.1 support the features of C++20 including ranges? Why do I get this error?
这与范围无关,clang 只是不完全支持 libstdc++ 在其实现中使用的 C++20 语言功能(在本例中 Down with typename!)。
我正在试验 C++20 范围,在使用 GCC 11.1.0 和 CMake 3.20.3 进行编译时出现以下奇怪行为。具体来说,以下代码无法编译:
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()));
}
导致非常长的错误消息,例如
[...] 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> >
和
[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] | ~~~~~~~~~~~~~^~~
但是,当我将 x
的大小转换为 long int
时,如注释行中所示,一切都可以正常编译。 这种行为是预期的吗?还是我的编译器设置有问题?
最终,当我使用 Clang 12.0.1 时,根本无法编译任何内容,并且出现以下错误:
[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] ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Clang 12.0.1 不应该支持 C++20 的特性,包括范围吗?为什么会出现此错误?
这是一个库错误,将由 P2367 修复,因为它被指定用于 take_view{E, F}
(这将是一个收缩转换)而不只是 take_view(E, F)
(这会很好)。与此同时,你必须相应地进行转换。
还有这个:
std::views::all(x) | std::views::take(x.size());
只是写的很长:
x | std::views::take(x.size());
您应该很少(如果有的话?)需要在用户代码中编写 views::all
。图书馆为您做这件事。
Shouldn't Clang 12.0.1 support the features of C++20 including ranges? Why do I get this error?
这与范围无关,clang 只是不完全支持 libstdc++ 在其实现中使用的 C++20 语言功能(在本例中 Down with typename!)。