我有以下代码,由于某种原因,只有最后一个块不起作用。
我最初认为这可能与
unique_ptr
仅移动或 std::set
具有 const 键有关,但随后不清楚为什么其他块起作用。
namespace sr = std::ranges;
namespace sv = std::views;
int main() {
{
std::set<int> up_s{10,20};
const auto up_vec = sv::as_rvalue(up_s) | sr::to<std::vector>();
assert(up_vec.size() == 2);
}
{
std::vector<std::unique_ptr<int>> up_d;
up_d.emplace_back(std::make_unique<int>(10));
up_d.emplace_back(std::make_unique<int>(20));
const auto up_vec = sv::as_rvalue(up_d) | sr::to<std::vector>();
assert(up_vec.size() == 2);
}
{
std::set<std::unique_ptr<int>> up_d;
up_d.emplace(std::make_unique<int>(10));
up_d.emplace(std::make_unique<int>(20));
//const auto up_vec = sv::as_rvalue(up_d) | sr::to<std::vector>();
//assert(up_vec.size() == 2);
}
}
错误消息似乎没用,因为看起来由于某种原因代码想要将
unique_ptr
视为范围
/opt/compiler-explorer/gcc-trunk-20240513/include/c++/15.0.0/ranges:9354:25:错误:静态断言失败 9354 | 9354 static_assert(input_range
>); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /opt/compiler-explorer/gcc-trunk-20240513/include/c++/15.0.0/ranges:9354:25:注意:不满足约束
...
/opt/compiler-explorer/gcc-trunk-20240513/include/c++/15.0.0/bits/ranges_base.h:499:13: 满足 'range<_Tp>' [with _Tp = const std::unique_ptr
&&] /opt/compiler-explorer/gcc-trunk-20240513/include/c++/15.0.0/bits/ranges_base.h:499:21: 在 '_Tp& __t' 的要求中 [with _Tp = const std::unique_ptr &&] /opt/compiler-explorer/gcc-trunk-20240513/include/c++/15.0.0/bits/ranges_base.h:501:22: 注意:所需的表达式 'std::ranges::_Cpo::begin(__t)' 是 无效 501 |范围::开始(__t); | ~~~~~~~~~~~~~^~~~~ /opt/compiler-explorer/gcc-trunk-20240513/include/c++/15.0.0/bits/ranges_base.h:502:20: 注意:所需的表达式 'std::ranges::_Cpo::end(__t)' 无效 502 | 502范围::结束(__t);
我最初认为这可能与
仅移动或unique_ptr
具有std::set
键有关,但随后不清楚为什么其他块起作用。const
你说得一针见血。很难从错误中辨别出来,而且我无法生成一些使其显而易见的错误消息,但简而言之,问题是
std::set
只能让我们访问 const
键,而 std::unique_ptr
会需要一些非常量才能使移动成为可能。
通过
as_rvalue
传输此范围并不能解决此问题;这只是意味着我们正在使用一系列类型为 const std::unique_ptr
的 xvalue,但这并不好。以下代码格式不正确,您尝试创建向量也是如此:
const std::unique_ptr<int> p;
auto q = std::move(p); // call to deleted copy constructor, ill-formed
在
std::set<int>
的情况下,常量并不重要。
std::set<int>
是 const int
左值的范围,通过管道将其通过 as_rvalue
使其成为 const int
x 值的范围。
下面的代码很好,从这样的范围构造 std::vector<int>
也可以:
const int x = 0;
int y = std::move(x); // initialization of an int from an xvalue of type const int
在
std::vector<std::unique_ptr<int>>
的情况下,常量不是问题。
std::vector
为我们提供了对元素的非常量访问,因此通过 as_rvalue
进行管道传输为我们提供了一系列非常量 std::unique_ptr
xvalues。
因此,将为每个元素调用移动构造函数。