2015-11-02 160 views
-3

我创建了一个类Route,我想将其存储在std::set中。一个路由索引的Id,所以我想要的是能够有一个像在自定义比较器中查找std :: set中的元素

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 
}; 
+1

['的std :: find_if'](http://en.cppreference.com/w/cpp/algorithm/find ) – Biffen

+1

...但问题是什么?! – Biffen

+0

@Biffen:'find_if'将是'O(n)',而理论上可以在'O(log n)' – Jarod42

回答

2

我假设你想使用用C++ 14加入std::set::findtemplate d超载。在此之前,您只能使用find()作为std::set所使用的Key类型的密钥。因此,首先要做的就是使用C++ 14编译器。其次,如果所得到的比较具有与构建(临时)密钥相同的语义并且将其与比较器比较,则额外的重载只能起作用。如果我没有遗漏任何东西,你的比较者将有资格获得这个资格。但是,为避免意外错误,您必须明确确认,通过给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; 
} 
+0

我没有C++ 14编译器。目前我使用的Visual Studio 2010是关于C++ 11(不完全)的。所以如果我理解你的评论,这是行不通的,因为编译器中缺少funcitionallity?但即便如此,施工人员不应该确保比较仍然有效吗?它至少适用于非指针版本。 – Devolus

+0

你可以从const char []中构造一个临时'Route'(你为此转换写了一个构造函数)。但是你不能从'const char *'构造一个临时的'Route *'。就Visual Studio而言,我不知道他们的支持,但是这个功能是由其中一位维护人员提出的,所以您可能有机会很早就采用它。你必须咨询你的文档。官方介绍在C++ 14中。 – 5gon12eder

+0

我也试过,但后来我得到不同的编译器错误。我尝试创建一个SSCE。 – Devolus

0

您也可以重载operator&,以允许在临时对象上调用它。这将简化使用方法,因为您可以即时创建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; 
}