我正在玩容器类型,深入细节并尝试构建一个不可修改的(或不可变的)地图。
为此,我构建了一些像copy-constructor来将另一个unordered_map中的所有元素添加到我的UnmodifiableMap(它基本上是std :: unordered_map的包装器)。为了使其不可修改,我只提供const迭代器和只读方法。但我对构造函数感到困惑,我确信我会错过一些东西,也许有人可以在这里指出我的问题。也许这是一种完全错误的方式,但到目前为止他的尝试是:
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=
的实现?!
答案 0 :(得分: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) {}