C++ 我可以合法地使用带有重载运算符()的结构作为std::upper_bound的比较吗?
我有这样的结构(类型经过简化以保留该点),生活在C++ 我可以合法地使用带有重载运算符()的结构作为std::upper_bound的比较吗?,c++,c++11,stl,language-lawyer,C++,C++11,Stl,Language Lawyer,我有这样的结构(类型经过简化以保留该点),生活在std::vector: struct Region { int first; int count; struct Metadata region_metadata; }; 在向量中,它们按第一个排序。如果添加第一个和计数,则获得下一个区域的第一个;所以基本上这个结构向量描述了连续数字范围的元数据 现在给定一个整数,我想查找元数据。在对区域进行排序时,我可以使用std::upper\u-bound。我是这样实施的: str
std::vector
:
struct Region {
int first;
int count;
struct Metadata region_metadata;
};
在向量中,它们按第一个
排序。如果添加第一个
和计数
,则获得下一个区域的第一个
;所以基本上这个结构向量描述了连续数字范围的元数据
现在给定一个整数,我想查找元数据。在对区域进行排序时,我可以使用std::upper\u-bound
。我是这样实施的:
struct Comp
{
inline bool operator()(const Region ®ion, int index) const
{
return region.first < index;
}
inline bool operator()(int index, const Region ®ion) const
{
return index < region.first;
}
};
现在这种情况发生了,因为上限
可以在内部选择符合其要求的重载,因为它同时调用Comp()(Region,int)
和Comp()(int,Region)
(这就是[](const Region®,int index){…
不起作用的原因)
实际上,我是通过跟踪使用前面提到的lambda时的错误消息来找到解决方案的。关于第四个论点:
比较函数对象(即满足
要求(比较)返回哪个如果第一个参数为
不到第二个
比较函数的签名应与
以下:
bool cmp(const Type1 &a, const Type2 &b);
签名不需要有常量&
,而是函数对象
不能修改传递给它的对象。类型Type1
和Type2
必须使类型为T
的对象可以隐式转换为
Type1
和Type2
,以及类型为ForwardIt
的对象都可以
取消引用,然后隐式转换为Type1
和Type2
类型Type1
必须使类型T
的对象
隐式转换为Type1
。类型Type2
必须确保
类型为ForwardIt
的对象可以取消引用,然后隐式引用
已转换为类型2
。
(自从我发布了这个问题,谢谢@T.C.)
这里,T
是std::upper_bound
的第三个参数,ForwardIt
是前两个参数的类型。这段引文并没有提到函数对象实际上是一个结构,它重载了它的操作符()
,以覆盖“正向”和“反向”情况
那么,在编写的规则中,这是合法的,还是我的特定编译器/标准库组合(g++5.3.1)的产物
我对C++14或C++17的特定答案感兴趣
完整示例:
#include <algorithm>
#include <iostream>
#include <vector>
struct Region {
Region(int first, int count, int n):
first(first),
count(count),
n(n)
{
}
int first;
int count;
int n; // think struct Metadata
};
struct Comp
{
inline bool operator()(const Region ®ion, int index) const
{
return region.first < index;
}
inline bool operator()(int index, const Region ®ion) const
{
return index < region.first;
}
};
int main() {
std::vector<Region> regions;
regions.emplace_back(0, 10, 1);
regions.emplace_back(10, 10, 2);
regions.emplace_back(20, 10, 3);
const int lookup = 10;
auto iter = std::upper_bound(
regions.begin(),
regions.end(),
lookup,
Comp());
// yes, I omitted error checking here, with error being iter == regions.begin()
std::cout << lookup << " is in region with n = " << (iter-1)->n << std::endl;
}
#包括
#包括
#包括
结构域{
区域(整数优先,整数计数,整数n):
第一(第一),,
数(数),,
n(n)
{
}
int优先;
整数计数;
int n;//思考结构元数据
};
结构组件
{
内联布尔运算符()(常量区域和区域,整数索引)常量
{
返回区域.first上限
可以在内部选择
符合其要求的重载,如它所称
Comp()(Region,int)
和Comp()(int,Region)
(这就是[](const Region®,int index){…}
不起作用的原因)
不,upper\u-bound
只调用Comp
的第二个重载。这正是您的(修复-谢谢@T.C.!)引用的内容:比较器的第一个参数始终是upper\u-bound
的第三个参数。应该交换lambda的参数
在比较器中为上界
/下界
重载运算符()
本质上是没有意义的,因为这些算法只会选择一个重载
operator()
应该像您在使用equal_range
时所显示的那样重载,这样做是合法的,因为比较器(或任何与此相关的函子)的内部细节与库无关:您只需要确保顺序严格(即正确的语义)而且重载是明确无误的。你说得很对。这可能会使这个问题偏离主题。我把lambda的论点搞砸了,并假设它们是正确的,所以我添加了重载,这当然使它起了作用。但由于我的假设是不正确的,所以结论也是正确的;它本来是有效的(事实上是有效的)(int,Region)重载。问题仍然存在。我们可以依靠算法函子的重载解析吗,也就是说,这对equal_range
@sp2d足够公平。啊,@T.C.,这也解释了我的困惑:-)。谢谢。
#include <algorithm>
#include <iostream>
#include <vector>
struct Region {
Region(int first, int count, int n):
first(first),
count(count),
n(n)
{
}
int first;
int count;
int n; // think struct Metadata
};
struct Comp
{
inline bool operator()(const Region ®ion, int index) const
{
return region.first < index;
}
inline bool operator()(int index, const Region ®ion) const
{
return index < region.first;
}
};
int main() {
std::vector<Region> regions;
regions.emplace_back(0, 10, 1);
regions.emplace_back(10, 10, 2);
regions.emplace_back(20, 10, 3);
const int lookup = 10;
auto iter = std::upper_bound(
regions.begin(),
regions.end(),
lookup,
Comp());
// yes, I omitted error checking here, with error being iter == regions.begin()
std::cout << lookup << " is in region with n = " << (iter-1)->n << std::endl;
}