Ale*_*104 28 c++ constants c++20 std-ranges
void foo(const auto& collection)
{
*collection.begin() = 104;
}
int main()
{
std::vector<int> ints {1, 2, 3, 4, 5};
foo(ints); // Error, as it should be
foo(ints | std::views::all); // Compiles and modifies the vector. Why?
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果函数的参数是类型,为什么左值引用的常量性会被完全忽略std::view?
编辑:
如果,正如您在注释中所写,const 视图引用与此上下文中的 const 指针类似,那么如果同一函数采用从右值对象构造的视图作为参数,为什么代码无法编译?
std::vector<int> getVec()
{
return std::vector{1, 2, 3, 4, 5};
}
void foo(const auto& collection)
{
*collection.begin() = 104; // Error: assignment of read-only location
}
int main()
{
foo(getVec() | std::views::all); // Nope!
return 0;
}
Run Code Online (Sandbox Code Playgroud)
Nic*_*las 29
尽管有名称,视图不一定是不可修改的。一般来说,表示一系列包含对象的类如何传播const取决于使用什么类。这就是事情变得奇怪的地方。
看,返回类型的views::all(e) 变化取决于 到底e是什么。如果e是一个泛左值(并且本身不是视图),那么它返回ref_view表示的范围的a e。ref_view其行为就好像它存储了一个指向给定范围的指针。当然,如果你有R*一个类的成员,const那么相当于R * const, not R const*。因此ref_view无法传播const到包含的范围。
但是,如果e是纯右值(并且也不是视图),那么all返回的是owning_view. 这个对象实际上存储了一个副本(e好吧,它从它移动)作为成员。这意味着当您获得 a 时const owning_view,它const会传播到该成员。由于const vector<T> 会传播const,所以 aviews::all(e)的纯右值也会传播vector。