dan*_*lNJ 3 c++ c++20 std-ranges
我试图将我认为是纯右值的内容传递到范围适配器闭包对象中。除非我将名称绑定到初始值设定项列表并使其成为左值,否则它不会编译。这里发生了什么?
#include <bits/stdc++.h>
using namespace std;
int main(){
//why does this compile?
auto init_list = {1,2,4};
auto v = init_list | views::drop(1);
//but not this?
// auto v2 = initializer_list<int>{1,2,4} | views::drop(1);
//or this?
//auto v3 = views::all(initializer_list<int>{1,2,4}) | views::drop(1);
}
Run Code Online (Sandbox Code Playgroud)
当您使用r | views::drop(1)创建新的时view,范围适配器会自动转换r为view适合您的。这要求 的类型r必须为viewable_range:
template<class T>\n concept viewable_\xc2\xadrange =\n range<T> &&\n ((view<remove_cvref_t<T>> && constructible_\xc2\xadfrom<remove_cvref_t<T>, T>) ||\n (!view<remove_cvref_t<T>> &&\n (is_lvalue_reference_v<T> || (movable<remove_reference_t<T>> && !is-initializer-list<T>))));\nRun Code Online (Sandbox Code Playgroud)\n请注意最后一个要求:
\n(is_lvalue_reference_v<T> || (movable<remove_reference_t<T>> && !is-initializer-list<T>))));\nRun Code Online (Sandbox Code Playgroud)\n由于 的类型r不模拟 a view,在您的情况下是initializer_list,它需要是一个左值,允许我们自由地获取它的地址来构造 a ,ref_view而不必担心悬空。
或者,我们需要它是movable,这允许我们将其所有权转移到owning_view,这意味着以下是格式良好的:
auto r = std::vector{42} | views::drop(1)\nRun Code Online (Sandbox Code Playgroud)\n但在这种情况下,我们还需要它不成为 的特化initializer_list,因为我们无法转移它的所有权,initializer_list只能复制。这就是你的例子失败的原因。