[英]How to use transform_iterator of unique_ptr in std algorithm
I am trying to call lower_bound
on transformed iterators of a vector<unique_ptr>>.
我试图在
vector<unique_ptr>>.
转换迭代器上调用lower_bound
vector<unique_ptr>>.
Similar questions had been asked previously on SO. 之前曾就SO问过同样的问题。 This one is slightly more complex that solutions to other problems are not readily applicable.
这个问题稍微复杂一些,其他问题的解决方案并不容易适用。
The problem is the same. 问题是一样的。 The std implementation calls unique_ptr operator= when it assigns
__first
to __middle
during the search. 性病实现调用的unique_ptr运营商=当分配
__first
到__middle
在搜索过程中。 In this example, a list of transformed objects (int->double) are searched to locate the element equal to or greater than the input (double). 在此示例中,搜索变换对象列表(int-> double)以定位等于或大于输入(double)的元素。
int main ()
{
vector<unique_ptr<int>>v {
std::make_unique<int>(0),
std::make_unique<int>(1),
std::make_unique<int>(2),
std::make_unique<int>(3),
std::make_unique<int>(4),
};
auto transFunc = [](const unique_ptr<int>& m) -> double {
return (*m) * 2.;
};
auto first = boost::make_transform_iterator(begin(v), transFunc);
auto last = boost::make_transform_iterator(end(v), transFunc);
auto i = lower_bound(first, last, 5.);
return 0;
}
I also tried using move_iterator's. 我也尝试过使用move_iterator。
auto transFunc = [](unique_ptr<int>&& m) -> double {
return (*m) * 2.;
};
auto first = boost::make_transform_iterator(
make_move_iterator(begin(v)), transFunc);
auto last = boost::make_transform_iterator(
make_move_iterator(end(v)), transFunc);
It seems like boost didn't carry the right-valueness forward in the transformed iterators. 似乎boost在转换的迭代器中没有带来正确的价值。
The code used to work in VS2013 but doesn't work in VS2015 or GNU. 该代码曾用于VS2013,但在VS2015或GNU中不起作用。
The lambda isn't copyable, and by default transform_iterator
does retain a copy of the callable. lambda不可复制,默认情况下
transform_iterator
会保留可调用的副本。
Simple solution: std::ref
or std::cref
: 简单的解决方案:
std::ref
或std::cref
:
#include <memory>
#include <boost/iterator/transform_iterator.hpp>
#include <vector>
int main ()
{
auto transFunc = [](const std::unique_ptr<int>& m) -> double { return (*m) * 2; };
std::vector<std::unique_ptr<int>> v;
v.push_back(std::make_unique<int>(0));
v.push_back(std::make_unique<int>(1));
v.push_back(std::make_unique<int>(2));
v.push_back(std::make_unique<int>(3));
v.push_back(std::make_unique<int>(4));
auto first = boost::make_transform_iterator(begin(v), std::cref(transFunc));
auto last = boost::make_transform_iterator(end(v), std::cref(transFunc));
auto i = lower_bound(first, last, 5.);
}
Create a copyable calleable instead: 改为创建一个可复制的calleable:
struct { double operator()(const std::unique_ptr<int>& m) const { return (*m) * 2; }; } transFunc;
#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/phoenix.hpp>
#include <vector>
#include <memory>
using namespace boost::adaptors;
using namespace boost::phoenix::arg_names;
int main () {
std::vector<std::unique_ptr<int>> v(5);
boost::generate(v, [n=0]() mutable { return std::make_unique<int>(n++); });
auto i = boost::lower_bound(
v |
indirected |
transformed(2. * arg1), 5.);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.