在自定义比较器的std :: set中查找元素

时间:2015-11-02 15:39:17

标签: c++ stdset

我创建了一个类Route,我希望将其存储在std::set中。路由是由Id索引的,所以我想要的是能够有一个像

这样的表达式
class RouteTemplate
{
    Route *RouteTemplate::getRoute(const char *pId);
    Route::ptr_set mRoutes;
};

Route *RouteTemplate::getRoute(const char *pId)
{
    Route::ptr_set::const_iterator pos = mRoutes.find(pId);
    if(pos == mRoutes.end())
        return NULL;

    return *pos;
}

但是我收到编译错误。

conversion from 'const char *' to 'Route *const ' not possible

据我所知,我必须实施比较器,我做了。

class Route
{
public:
    static const size_t _id_len = 11;

    class comparator
    {
    public:
        bool operator() (const Route &oLeft, const Route &oRight) const
        {
            return oLeft < oRight;
        }
    };
    class ptr_comparator
    {
    public:
        bool operator() (const Route *oLeft, const Route *oRight) const
        {
            return (*oLeft) < (*oRight);
        }
    };

    typedef std::set<Route, Route::comparator> set;
    typedef std::set<Route *, Route::ptr_comparator> ptr_set;

public:
    Route(void);
    Route(const char *oId);
    virtual ~Route(void) {};

    inline bool operator<(const Route &oOther) const
    {
        return strncmp(mId, oOther.mId, _id_len) < 0;
    }

    inline bool operator<(const char *oId) const
    {
        if(!oId)
            return false;

        return strncmp(mId, oId, _id_len) < 0;
    }

    inline const char *getId(void) const { return mId; }
    inline void setId(const char *oId)
    {
        if(oId == NULL)
            mId[0] = 0;
        else
        {
            strncpy(mId, oId, sizeof(mId));
            mId[_id_len] = 0;
        }
    }

private:
    char mId[_id_len+1];
    // Additional members
};

2 个答案:

答案 0 :(得分:2)

我假设你想利用在C ++ 14中添加的std::set::findtemplate d重载。在此之前,您只能find() Key用于std::set的{​​{1}}类型的密钥。因此,首先要做的是使用C ++ 14编译器。

其次,额外的重载只能在结果比较具有与构造(临时)密钥相同的语义并将其与std::set比较器进行比较时才起作用。如果我没有遗漏任何东西,你的比较者就有资格获得这个。但是,为避免意外错误,您必须明确确认Compare类型为类型成员is_transparent

如果您可以使用临时创建,您可以明确要求它。这应该有用。

Route *RouteTemplate::getRoute(const char *pId)
{
    Route temporary_key {pId};
    Route::ptr_set::const_iterator pos = mRoutes.find(&temporary_key);
    if(pos == mRoutes.end())
        return NULL;
    return *pos;
}

答案 1 :(得分:0)

您还可以重载operator&,以允许在临时对象上调用它。这样可以简化find方法的使用,因为您可以动态创建Route对象,然后在此临时应用operator&

class Route
{
public:
...
    Route* operator&() { return this; }
...
}

然后编写像getRoute()这样的方法是有效的:

Route *RouteTemplate::getRoute(const char *pId)
{
    Route::ptr_set::const_iterator pos = mRoutes.find(&Route(pId));
    if (pos == mRoutes.end())
        return NULL;

    return *pos;
}