2013-04-07 58 views
1

我查看了一些關於const限定符的文章,但我無法弄清楚如何解決此問題。我建立在所述STL地圖類設計的一類,並且我使用STL組類的基類:在模板運算符[]中刪除「const int」限定符[]

template <class Key, class Value> 
class map : public std::set <std::pair<Key, Value> > { 
public: 
    typedef std::set<std::pair<Key, Value> > parent; 
    typedef typename std::set<std::pair<Key, Value> >::iterator iterator; 

    // constructors 
    map() : parent() {} 
    map(map<Key, Value>& m) : parent(m) {} 

    // definition for subscript operator 
    Value& operator [] (const Key &); 

    // overloaded methods from set 
    void erase(Key&); 
    void erase(iterator& itr) { 
     parent::erase(itr); 
    } 

    int count(Key&); 
    iterator find(Key&); 
    iterator lower_bound(Key& k) { 
     return parent::lower_bound(k); 
    } 

    iterator upper_bound(Key& k) { 
     return parent::upper_bound(k); 
    } 

    // not found iterator 
    iterator end() { 
     return parent::end(); 
    } 

}; 

的問題是與運營商[]過載功能,它看起來像:

template <class Key, class Value> 
Value& map<Key, Value>::operator[] (const Key& k) { 
    std::pair<Key, Value> test; 
    test.first = k; 

    std::pair<iterator, bool> where = parent::insert(test); 

    return (*(where.first)).second; 
} 

編譯器給我的錯誤「... map.h:108:16:將引用綁定到類型'int'到類型'const int'的值落入限定符」。我意識到,這是鑑於(*(where.first))第二個被評估爲「const int的」,我這回的「詮釋」,因爲我已經聲明瞭一個地圖爲:

map<std::string, int> mymap; 
mymap["one"] = 1; 

它看起來std::pair<...>被定義爲std::pair<std::string, const int>而不是std::pair<std::string, int>。至少這是我的猜想。我必須錯過簡單的事情,但我沒有看到它。任何幫助是極大的讚賞。

+2

通常,避免從'std'容器繼承。它們不是爲了繼承而設計的。使用「has-a」而不是「is-a」。其次,你在'std :: set'上的排序是錯誤的,因爲'std :: pair :: operator <'是完全獨立的,你不想在'Value'上排序。 – Yakk 2013-04-07 19:04:44

+0

一般來說,這是事實。但這實際上是我打算在基於學生問題的課程中使用的一個示例。我沒有在Value上訂購。我將返回要由另一個值放置的值的引用。但下面的評論澄清了爲什麼我不能這樣做。相反,我採取了不同的方法。 '謝謝。 – CHardnett 2013-04-08 04:16:07

+0

不,上面的代碼先按'Key',然後再按'Value'。如果你修改'set'中的'Value',你的'operator []'甚至不會再找到'pair '!它會找到一個完全不同的條目。 – Yakk 2013-04-08 04:23:52

回答

3

問題是std::set元素是不可變的(否則你可以任意修改它們,並且在set不知道它的情況下弄亂順序);這是通過返回const迭代器的方法來實現的。

因此,*(where.first)const,因此也是(*(where.first)).second。所以你不能返回非const引用。

+0

謝謝,這是有道理的。我忘記了這些鍵/值本質上是相同的。我會以另一種方式來做。 – CHardnett 2013-04-08 04:05:05

+0

@CHardnett,這是真的,但是如果你知道你應用的操作將保留元素/鍵的順序,你可以通過'const_cast'改變元素。 (例如,你可以乘以一個常數的所有數字)。像往常一樣,只有當你知道編譯器不知道的東西時,才應該謹慎使用。 – alfC 2013-10-08 19:19:29