如何在std算法

时间:2018-04-02 20:31:24

标签: c++ c++11 boost

我试图在lower_bound的转换迭代器上调用vector<unique_ptr>>.。之前已经在SO上提出了类似的问题。这个问题稍微复杂一些,因此其他问题的解决方案并不适用。

问题是一样的。 std实现在搜索期间将__first分配给__middle时调用unique_ptr operator =。在此示例中,搜索变换对象列表(int-&gt; 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;
}

我也尝试过使用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);  

似乎boost在转换后的迭代器中没有带来正确的价值。

用于在VS2013中工作但在VS2015或GNU中不起作用的代码。

1 个答案:

答案 0 :(得分:1)

lambda不可复制,默认情况下transform_iterator会保留可调用的副本。

简单解决方案:std::refstd::cref

<强> Live On Coliru

#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.);
}

可替换地:

创建一个可复制的calleable:

struct { double operator()(const std::unique_ptr<int>& m) const { return (*m) * 2; }; } transFunc;

<强> Live On Coliru

加成

<强> Live On Coliru

#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.);
}