我试图将我认为是纯右值的内容传递到范围适配器闭包对象中。除非我将名称绑定到初始值设定项列表并使其成为左值,否则它不会编译。这里发生了什么?
#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);
}
当你使用r | views::drop(1)
创建一个新的view
,范围适配器将自动转换r
into a view
为你。这要求类型r
必须模型viewable_range https://en.cppreference.com/w/cpp/ranges/viewable_range:
template<class T>
concept viewable_range =
range<T> &&
((view<remove_cvref_t<T>> && constructible_from<remove_cvref_t<T>, T>) ||
(!view<remove_cvref_t<T>> &&
(is_lvalue_reference_v<T> || (movable<remove_reference_t<T>> && !is-initializer-list<T>))));
请注意最后一个要求:
(is_lvalue_reference_v<T> || (movable<remove_reference_t<T>> && !is-initializer-list<T>))));
由于类型为r
不建模view
,在你的情况下是initializer_list
,它需要是一个lvalue,允许我们自由地获取它的地址来构造一个ref_view https://en.cppreference.com/w/cpp/ranges/ref_view无需担心悬挂。
或者,我们需要它是movable
,这使我们能够将其所有权转让给owning_view https://en.cppreference.com/w/cpp/ranges/owning_view,这意味着以下内容是格式良好的:
auto r = std::vector{42} | views::drop(1)
但在这种情况下,我们也需要它不成为initializer_list
,因为我们无法转让它的所有权,initializer_list
总是复制。这就是你的例子失败的原因。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)