繁体   English   中英

使用 `std::equal_range` 和 `boost::transform_iterator`

[英]Using `std::equal_range` with `boost::transform_iterator`

假设我有一个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

任何帮助,将不胜感激!

您可以使用具有不同类型的std::set::find来避免构造Item 请注意,您的套装只能包含一个具有特定 position 的项目。

您可以使Position直接与Item进行比较(添加Item{} < Position{}Position{} < Item{} )或创建新的代理 class:

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<>>;

您也可以使用完全不同的比较器来使PositionItem进行比较。

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
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM