2013-02-15 3 views
0

Я играю с типами контейнеров, получая детали и пытаюсь построить неизменяемую (или неизменяемую) карту.Обертка unordered_map для создания неизменяемой (неизменяемой) карты

Для этого я создал какой-то вроде конструктора копий, чтобы добавить все элементы из другого unordered_map в мою UnmodifiableMap (которая в основном является оберткой для std :: unordered_map). Чтобы сделать его немодифицированным, я предоставляю только константные итераторы и методы только для чтения. Но я застрял с конструктором, я уверен, что что-то упустил, может быть, кто-то может указать мне на проблему. Может быть, это совершенно неправильно, как это, но его то, что пытался до сих пор:

template <typename Key, typename T, 
    typename HashFcn = std::hash<Key>, 
    typename EqualKey = std::equal_to<Key>, 
    typename Alloc = std::allocator<std::pair<const Key, T> > > 
class UnmodifiableMap { 
public: 
    // The actual data 
    typedef std::unordered_map<T, Key, HashFcn, EqualKey> base; 

    typedef Key key_type; 
    typedef T data_type; 
    typedef T mapped_type; 
    typedef std::pair<const key_type, data_type> value_type; 
    typedef HashFcn hasher; 
    typedef EqualKey key_equal; 
    typedef Alloc allocator_type; 

    typedef typename base::size_type size_type; 
    typedef typename base::const_iterator const_iterator; 
    typedef typename base::iterator iterator; 

private: 
    base _map; 

    /** 
    * Constructs an empty unordered_map 
    */ 
    UnmodifiableMap(
     size_type n = 0, const hasher& hf = hasher(), 
     const key_equal& eql = key_equal(), 
     const allocator_type &alloc = allocator_type()) 
      : _map(n, hf, eql, alloc) {} 

public: 
    /** Constructs a copy of unordered_map */ 
    UnmodifiableMap(const base& other) 
    : _map(static_cast<const base&>(other)) {} 

    ~UnmodifiableMap() {} 

    iterator begin() { return _map.begin(); } 
    iterator end() { return _map.end(); } 
    const_iterator begin() const { return _map.begin(); } 
    const_iterator end() const { return _map.end(); } 

    bool empty() const { return _map.empty(); } 

    bool contains(const key_type& key) const { 
     return _map.find(key) != _map.end(); } 
}; 

И здесь главный корпус:

int main(int argc, char **argv) { 
    typedef std::unordered_map<int, std::string> Items; 
    Items map; 

    map[1] = "first string"; 
    map[4] = "string 4"; 
    map[5] = "string 5"; 
    map[22] = "string 22"; 
    map[12] = "string 12"; 
    map[18] = "string 18"; 

    typedef UnmodifiableMap<int, std::string> ReadOnlyItems; 
    ReadOnlyItems readonlymap(map); 

    return 0; 
} 

Я получаю ошибку на

Unmodifiable_map.cpp: In function ‘int main(int, char**)’: 
Unmodifiable_map.cpp:56:25: error: no matching function for call to ‘UnmodifiableMap<int, std::basic_string<char> >::UnmodifiableMap(Items&)’ 
Unmodifiable_map.cpp:56:25: note: candidates are: 
Unmodifiable_map.h:45:2: note: UnmodifiableMap<Key, T, HashFcn, EqualKey, Alloc>::UnmodifiableMap(const base&) [with Key = int, T = std::basic_string<char>, HashFcn = std::hash<int>, EqualKey = std::equal_to<int>, Alloc = std::allocator<std::pair<const int, std::basic_string<char> > >, UnmodifiableMap<Key, T, HashFcn, EqualKey, Alloc>::base = std::unordered_map<std::basic_string<char>, int, std::hash<int>, std::equal_to<int>, std::allocator<std::pair<const std::basic_string<char>, int> > >] 
Unmodifiable_map.h:45:2: note: no known conversion for argument 1 from ‘Items {aka std::unordered_map<int, std::basic_string<char> >}’ to ‘const base& {aka const std::unordered_map<std::basic_string<char>, int, std::hash<int>, std::equal_to<int>, std::allocator<std::pair<const std::basic_string<char>, int> > >&}’ 
Unmodifiable_map.h:37:2: note: UnmodifiableMap<Key, T, HashFcn, EqualKey, Alloc>::UnmodifiableMap(UnmodifiableMap<Key, T, HashFcn, EqualKey, Alloc>::size_type, const hasher&, const key_equal&, const allocator_type&) [with Key = int, T = std::basic_string<char>, HashFcn = std::hash<int>, EqualKey = std::equal_to<int>, Alloc = std::allocator<std::pair<const int, std::basic_string<char> > >, UnmodifiableMap<Key, T, HashFcn, EqualKey, Alloc>::size_type = long unsigned int, UnmodifiableMap<Key, T, HashFcn, EqualKey, Alloc>::hasher = std::hash<int>, UnmodifiableMap<Key, T, HashFcn, EqualKey, Alloc>::key_equal = std::equal_to<int>, UnmodifiableMap<Key, T, HashFcn, EqualKey, Alloc>::allocator_type = std::allocator<std::pair<const int, std::basic_string<char> > >] 
Unmodifiable_map.h:37:2: note: no known conversion for argument 1 from ‘Items {aka std::unordered_map<int, std::basic_string<char> >}’ to ‘long unsigned int’ 
Unmodifiable_map.h:14:7: note: UnmodifiableMap<int, std::basic_string<char> >::UnmodifiableMap(const UnmodifiableMap<int, std::basic_string<char> >&) 
Unmodifiable_map.h:14:7: note: no known conversion for argument 1 from ‘Items {aka std::unordered_map<int, std::basic_string<char> >}’ to ‘const UnmodifiableMap<int, std::basic_string<char> >&’ 
Unmodifiable_map.h:14:7: note: UnmodifiableMap<int, std::basic_string<char> >::UnmodifiableMap(UnmodifiableMap<int, std::basic_string<char> >&&) 
Unmodifiable_map.h:14:7: note: no known conversion for argument 1 from ‘Items {aka std::unordered_map<int, std::basic_string<char> >}’ to ‘UnmodifiableMap<int, std::basic_string<char> >&&’ 

Надеюсь, кто-то может пролить свет на это. Также я думаю, что мне нужно сделать больше в конструкторе копирования, возможно скопировать элементы (например, функцию swap) и реализацию operator=?!

+2

'константной зЬй :: Карта ReadOnlyItems (г)' не хватает? – Chad

+0

Это так, но, как я уже сказал, я немного поиграю/узнаю о типах контейнеров, поэтому просто хочу знать, что случилось с моей реализацией. Только для образовательных целей. –

+0

Что такое 'static_cast (другое)'? –

ответ

2

Вы обмениваетесь роль T и Key в вашем определении base типа внутри класса-оболочки:

template <typename Key, typename T, 
    typename HashFcn = std::hash<Key>, 
    typename EqualKey = std::equal_to<Key>, 
    typename Alloc = std::allocator<std::pair<const Key, T> > > 
class UnmodifiableMap { 
public: 
    // typedef std::unordered_map<T, Key, HashFcn, EqualKey> base; // ERROR 
    typedef std::unordered_map<Key, T, HashFcn, EqualKey> base; // OK 
    ... 

Следовательно, ваша основная карта заканчивает тем, unordered_map<string, int>, а не unordered_map<int, string>, а компилятор жалуется несоответствие.

Также обратите внимание, что у вас есть ненужный static_cast в конструкторе:

UnmodifiableMap(const base& other) 
// : _map(static_cast<const base&>(other)) {} // NOT NEEDED. Just do: 
    : _map(other) {} 
+0

Argh, thanx. В конце концов, я действительно не обращал внимания на 'typedef' базы. Полагаю, я слишком долго сидел над этим! Спасибо, что указали! –

+0

@ AndreasW.Wylach: Случается всем ;-) –

Смежные вопросы