2015-11-02 165 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; 
}