我正在用 C++ 编写一个库,为此我实现了一个带有类型擦除的地图包装器。包装器的结构与这篇精彩的文章一样:http ://www.cplusplus.com/forum/articles/18756/ 。
TLDR:
template<typename K, typename V>
class AnyMap
{
class MapConcept
{
public:
// Lots of pure virtual methods...
// These mimic the intersection of STL and Boost maps' interfaces
// Example:
virtual size_type size() = 0;
};
template<typename ActualMapType>
class MapModel : MapConcept
{
ActualMapType m;
public:
// Implementations of the parent's virtual methods...
// These basically just call the same method on member m.
// Example:
size_type size() { return m.size(); }
};
MapConcept* mapConcept;
public:
// Again, the STL and Boost maps' interface methods
// Example:
size_type size() { return mapConcept->size(); }
};
我不确定我是否会将此地图作为已完成库的一部分公开,还是将其作为辅助类隐藏起来,但无论哪种方式,我都想知道赋值运算符的作用。
目前,我有这样的事情:
AnyMap& AnyMap::operator=(const AnyMap& other) {
delete mapConcept;
mapConcept = other.mapConcept->clone();
return *this;
}
这意味着,如果我使用 STL 的映射和 Boost 的 unordered_map 创建两个映射,然后将一个分配给另一个,那么现在两者都将具有相同的映射类型。
std::map<string, int> stlMap;
boost::unordered_map<string, int> boostMap;
// insert some stuff into maps
AnyMap<string, int> stlAnyMap( stlMap );
AnyMap<string, int> boostAnyMap( boostMap );
stlAnyMap = boostAnyMap;
// now stlAnyMap has a copy of boostMap
所以,这是有道理的,因为分配给地图的内容是预期的。但是,我怀疑通常映射类型会因具有默认值的类型参数之一而有所不同(例如 Boost::unordered_map 中的哈希)。所以,也许它应该保留底层的地图类型。我认为,这可以通过以下方式完成:
AnyMap& AnyMap::operator=(const AnyMap& other) {
mapConcept->clear();
mapConcept->insert( other.mapConcept->begin(), other.mapConcept->end() );
return *this;
}
由于模板化的插入方法,这应该可以工作:
template <class InputIterator>
void insert (InputIterator first, InputIterator last);
顺便说一句,如果有人想知道我是如何处理迭代器的:我使用了 Thomas Becker 的 any_iterator - http://thbecker.net/free_software_utilities/type_erasure_for_cpp_iterators/any_iterator.html。
那么,你们怎么看?我倾向于后一种方法,但我想听听任何一方的任何论点。
提前致谢!
编辑:这是反对的第一个论点(也许,你可以告诉我这是多么重要):如果一个谓词区分映射中的两个键而另一个映射类型的内容现在可能一对一映射到另一个映射认为它们相同。