如何将迭代器传递给std :: lower_bound()比较函数?

时间:2018-02-14 15:48:32

标签: c++ std stl-algorithm

在以下来自cplusplus.com

的声明中
template<class ForwardIterator, class T, class Compare>
ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T& val, Compare comp);

comp()应该类似于:

template<class T>
bool comp(const T& v1, const T& v2);

问题是我不想在那里传递值类型。我想将迭代器传递给它,然后移动它们好吧,在解除引用之前,只需在comp()内静静地盯着它们。 (更不用说 - 记录它们。)有没有解决方法呢?

当然,我可以使用自己的迭代器编写自己的容器类,当然我可以编写自己的std::lower_bound()实现。两种选择都相当不愉快。

2 个答案:

答案 0 :(得分:1)

std::lower_bound doc,您可以阅读bool comp(const Type1 &a, const Type2 &b);

  

类型Type1必须使ForwardIt类型的对象可以取消引用,然后隐式转换为Type1。类型Type2必须使T类型的对象可以隐式转换为Type2

这意味着,std::lower_bound将始终使用范围中的元素作为左侧参数调用comp,并将value作为右侧参数。如果您的搜索范围是连续的范围(意味着您正在处理std::vectorstd::arraystd::valarraystd::string,...或C风格的数组),你可以从范围的开始和comp的左侧参数之间的距离设计一个迭代器:

auto v = std::vector<int>{0, 1, 2, 3, 4, 5};

auto comp = [&v](const int &lhs, const int &rhs)
{
    auto it_lhs = cbegin(v) + std::distance(std::addressof(*cbegin(v)), &lhs);
    return *it_lhs < rhs;
};

std::cout << *std::lower_bound(begin(v), end(v), 2, comp) << "\n";

答案 1 :(得分:0)

来自the doc

  

谓词函数的签名应该等同于   以下内容:

     

bool pred(const Type1 &a, const Type2 &b);

     

签名不需要const &,但函数不能   修改传递给它的对象。

所以你不能,也不应该这样做。 std::lower_bound具有特定目的,不应以任何方式修改输入。为此目的编写自己的函数。

如果您只需要索引,并且您的容器将其元素存储在线性,连续的内存块中,您可以执行此操作(使用std::vector示例):

std::vector<...> vec;
...
const auto* firstElemPtr = &vec[0];
std::lower_bound(vec.begin(), vec.end(), key, [firstElemPtr](const auto& left, const auto& right) -> bool {
  size_t index = &left - firstElemPtr;
  // now do the comparison
});