微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

C++20 范围和 std::views::take 错误

如何解决C++20 范围和 std::views::take 错误

我正在试验 C++20 范围,在使用 GCC 11.1.0 和 CMake 3.20.3 进行编译时出现以下奇怪的行为。具体来说,以下代码无法编译:

    const [searchKeyword,setSearchKeyword] = useState("")
   
    let value = new URLSearchParams(window.location.search).get("query")

    useEffect(() => {
        setSearchKeyword(value)
        axios.get(`http://127.0.0.1:8000/music/api/searchtrack/?search=${searchKeyword}`)
            .then(res => {
                setSongs(res.data)
            }).catch(err => {
                console.log(err)
            })
        },[searchKeyword])

导致很长的错误信息,例如

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 时,一切都可以正常编译。 这种行为是否符合预期?还是我的编译器设置有问题?

最终,当我使用 Clang 12.0.1 时,根本没有编译,并且出现以下错误

long int

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。图书馆为你做这件事。


Clang 12.0.1 不应该支持 C++20 的特性,包括范围吗?为什么会出现此错误?

这与范围无关,clang 只是不完全支持 libstdc++ 在其实现中使用的 C++20 语言功能(在本例中为 Down with typename!)。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。