说我有一个Item
的结构,我将它们存储在std::set
中,并按以下方式排序:
struct Position
{
int x;
int y;
}
struct Item
{
std::string id;
Position position;
// NOTE: only `position` should matter for equality
operator==(const Item& other)
{
return position == position;
}
};
inline bool operator<(const Item& lhs, const Item& rhs)
{
if (lhs.position.x == rhs.position.x)
{
return lhs.position.y < rhs.position.y;
}
return lhs.position.x < rhs.position.x;
}
using ItemSet = std::set<Item>;
除了要按std::equal_range
进行搜索外,我想使用ItemSet
来搜索Position
。我知道我可以做类似的事情:
ItemSet items;
Item tempItem;
tempItem.position = some_position;
auto result = std::equal_range(items.begin(), items.end(), tempItem);
但是我想避免使用临时Item
。
我试图像这样使用boost::transform_terator
:
auto tr = [](const Item& item) { return item.pos; };
auto tr_begin = boost::make_transform_iterator(items.begin(), tr);
auto tr_end = boost::make_transform_iterator(items.end(), tr);
Position findme { 2, 1 };
auto result = std::equal_range(tr_begin, tr_end, findme);
但是由于我不了解的原因而无法编译,即使它确实起作用,我如何从result
中将迭代器放入原始集合中?也许总体上有更好的方法可以做到这一点?
以下是一个测试工具,用于显示问题:http://cpp.sh/3hzsq
任何帮助将不胜感激!
答案 0 :(得分:1)
您可以将std::set::find
与其他类型一起使用,以避免构造Item
。请注意,您的集合只能包含一个具有特定位置的项目。
您可以使Position
与Item
直接相似(添加Item{} < Position{}
和Position{} < Item{}
)或创建新的代理类:
struct ItemPosition {
Position p;
};
inline bool operator<(const ItemPosition& l, const Item& r) {
return l.position.x == r.position.x ? l.position.y < r.position.y : l.position.x < r.position.x;
};
inline bool operator<(const Item& l, const ItemPosition& r) {
return l.position.x == r.position.x ? l.position.y < r.position.y : l.position.x < r.position.x;
};
// Change the comparator so it can compare with `ItemPosition` too
using ItemSet = std::set<Item, std::less<>>;
您也可以使用完全不同的比较器来使Position
与Item
具有可比性。
struct ItemComparator {
bool operator()(const Position& l, const Position& r) const {
return l.x == r.x ? l.y < r.y : l.x < r.x;
}
bool operator()(const Item& l, const Item& r) const {
return operator()(l.position, r.position);
}
bool operator()(const Item& l, const Position& r) const {
return operator()(l.position, r);
}
bool operator()(const Position& l, const Item& r) const {
return operator()(l, r.position);
}
using is_transparent = void;
};
using ItemSet = std::set<Item, ItemComparator>;
并像这样使用它:
Position findme { 2, 1 };
// Or just `items.find(findme)` if using a custom comparator
auto result = items.find(ItemPosition{ findme });
if (result == items.end()) {
// No item found
} else {
Item& item = *result;
// found item
}