将 lower_bound/upper_bound 与 2 种不同的类型一起使用

using lower_bound/upper_bound with 2 different types

本文关键字:bound 类型 一起 lower upper      更新时间:2023-10-16

我有一个小的工作代码,用于查找使用特殊比较方法的一系列项目。但是当我尝试用lower_bound()upper_bound()函数重写它时,我得到了一个奇怪的错误。我写了一个小代码来显示我的问题。这是代码:

#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;
int main() {
string str = "banana";
string keyword = "ana";
int sa_idx[] = {5, 3, 1, 0, 4, 2};
vector<int> sa(sa_idx, sa_idx + sizeof(sa_idx) / sizeof(int) );
auto cmp = [&str] (const int &a, const string &keyword) -> bool
{
return strncmp(str.c_str() + a,  keyword.c_str(), keyword.length()) < 0;
};
cout << (upper_bound(sa.begin(), sa.end(), keyword, cmp) - 
lower_bound(sa.begin(), sa.end(), keyword, cmp)) << endl;
return 0;
}

如您所见,比较函数使用数组sa关键字和值进行比较决策。一个标准说:

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

我的比较函数具有第一个参数int类型(因为数组vector<int>(和第二个参数类型(作为关键字类型(的string。但我不知道为什么我得到以下错误:

In file included from /usr/include/c++/6/bits/stl_algobase.h:71:0,
from /usr/include/c++/6/bits/char_traits.h:39,
from /usr/include/c++/6/ios:40,
from /usr/include/c++/6/ostream:38,
from /usr/include/c++/6/iostream:39,
from prog.cpp:1:
/usr/include/c++/6/bits/predefined_ops.h: In instantiation of ‘bool __gnu_cxx::__ops::_Val_comp_iter<_Compare>::operator()(_Value&, _Iterator) [with _Value = const std::__cxx11::basic_string<char>; _Iterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; _Compare = main()::<lambda(const int&, const string&)>]’:
/usr/include/c++/6/bits/stl_algo.h:2049:14:   required from ‘_ForwardIterator std::__upper_bound(_ForwardIterator, _ForwardIterator, const _Tp&, _Compare) [with _ForwardIterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; _Tp = std::__cxx11::basic_string<char>; _Compare = __gnu_cxx::__ops::_Val_comp_iter<main()::<lambda(const int&, const string&)> >]’
/usr/include/c++/6/bits/stl_algo.h:2114:32:   required from ‘_FIter std::upper_bound(_FIter, _FIter, const _Tp&, _Compare) [with _FIter = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; _Tp = std::__cxx11::basic_string<char>; _Compare = main()::<lambda(const int&, const string&)>]’
prog.cpp:19:57:   required from here
/usr/include/c++/6/bits/predefined_ops.h:173:11: error: no match for call to ‘(main()::<lambda(const int&, const string&)>) (const std::__cxx11::basic_string<char>&, int&)’
{ return bool(_M_comp(__val, *__it)); }
^~~~~~~~~~~~~~~~~~~~~~~~~~~
prog.cpp:14:61: note: candidate: main()::<lambda(const int&, const string&)>
auto cmp = [&str] (const int &a, const string &keyword) -> bool
^~~~
prog.cpp:14:61: note:   no known conversion for argument 1 from ‘const std::__cxx11::basic_string<char>’ to ‘const int&’

我错过了一些非常明显的东西吗?因为编译器似乎将string作为比较函数的第一个参数。

您的问题是std::uppper_bound要求签名的cmp

bool(T, decltype(*Iterator))

std::lower_bound有相反的要求,并且想要

bool(decltype(*Iterator), T)

因此,您不能同时使用同一个比较器来实现这两个功能。 还有其他方法可以修改代码,但只需添加第二个比较器,例如

auto cmp1 = [&str](const string &keyword, const int &a) -> bool 
{ 
return strncmp(keyword.c_str(), str.c_str() + a, keyword.length()) < 0;
};
auto cmp2 = [&str] (const int &a, const string &keyword) -> bool
{
return strncmp(str.c_str() + a,  keyword.c_str(), keyword.length()) < 0;
};
cout << (upper_bound(sa.begin(), sa.end(), keyword, cmp1) - 
lower_bound(sa.begin(), sa.end(), keyword, cmp2)) << endl;

允许编译代码。