std :: map:仅使用keytype的一部分进行比较和查找

时间:2015-03-09 11:36:50

标签: c++ c++11 dictionary stl

我有一张地图使用某种数据类型KT的作为映射到矩阵类型的键,即某事物。喜欢

std::map<std::pair<KT,KT>, MatType, PairCompare>

为了比较,我只需要该对的第一个元素,因此PairCompare非常简单

struct PairCompare
{
    bool operator()(const std::pair<KT,KT>& lhs,const std::pair<KT,KT>& rhs) const
    {return lhs.first<rhs.first;}
};

然而,我想将整个对用作关键字,因为在迭代地图时我经常需要操作中的第二个元素。

有时,我还需要找到基于单个 KT的地图条目。当然我应该在 find()例程中使用一对KT,但我想避免创建一对虚拟KT,因为我必须多次这样做并且可能会变得昂贵。我想使用像

这样的东西
std::map<std::pair<KT,KT>, MatType, PairCompare> mymap;
KT mykey = // ... some implementation of KT;

// fill map

auto it = mymap.find(mykey); // <- will not work of course, but what I would like to use
auto it = mymap.find(std::pair<KT,KT>(mykey,mykey)); // <- what I am using so far (creating a dummy pair)

Mykey通常可以是左值和右值(在我的应用程序中)。

是否有任何方法可以定义包含两个KT实例的不同类型的键,并且只使用一个用于地图排序,还可以通过单个 KT直接查找?可以用一些特殊的比较对象来完成吗?也许还有一种聪明的方法可以使用KT对作为Key,但是仍然允许在地图迭代中访问第二个KT?

感谢您的帮助!

P.S。:确切地说,正如KT我正在使用

typedef std::vector<int> KT

1 个答案:

答案 0 :(得分:2)

你的问题是你认为键是“X,Y对”。将密钥视为“支持此操作和操作的对象”:

template<typename K1, typename K2>
class Key
{
    K1 v1_;
    boost::optional<K2> v2_;
public:
    Key(K1 v1): v1_{ std::move(v1) }, v2_{} {}
    Key(K1 v1, K2 v2): v1_{ std::move(v1) }, v2_{ std::move(v2) } {}
    bool operator==(const Key<K1,K2>& other)
    {
        if(!v2_ || !other.v2_)
            return v1_ == other.v1_;
        return std::tie(v1_, *v2_) == std::tie(other.v1_, *other.v2_);
    }
    // implement other comparisons, as required
};

using KeyType = Key<int,std::string>;
std::map<KeyType, MatType> YourMap;
// add key comparable by first element:
YourMap[KeyType{0}] = MatType{}; // match KeyType{0, "any string"}
// add key comparable by both elements:
YourMap[KeyType{1, "test"}] = MatType{}; // match KeyType{1, "test"}

尝试强制键成为一对使问题复杂化。