std::views打破了const吗?


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;
}

如果函数的参数是std::view类型,为什么左值引用的constness被完全忽略?

编辑:
如果,正如你在评论中所写的,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;
}

视图,尽管名称,不一定是不可修改的。一般来说,表示包含对象序列的类如何传播const取决于使用的是什么类。这就是奇怪的地方。

看,views::all(e)的返回类型改变取决于e是什么。如果e是一个glvalue(它本身不是一个视图),那么它返回e表示的范围内的ref_viewref_view的行为就好像它存储了一个指向给定范围的指针。当然,如果您有一个类的R*成员,那么等价的constR * const,而不是R const*。因此,ref_view不能将const传播到所包含的范围。

然而,如果e是一个右值(同样不是视图),那么all返回的是一个owning_view。该对象实际上e的副本存储为成员。这意味着当您获得const owning_view时,该const将传播到该成员。既然const vector<T>会传播const,那么views::all(e)的右值也会传播vector

最新更新