我从本质上讲是一个包含std :: map的类,其中的值是shared_ptrs,其中包裹着容纳不同类型的容器。骨架代码如下:
// Just a basic example class
class MyClass {
public:
explicit MyClass(int i) : mI(i) {}
bool operator==(const MyClass& rhs) { return mI == rhs.mI; }
private:
int mI;
};
// A class into which key value pairs can be added where the value
// can be of a different type.
class MultipleTypeMap {
public:
template <typename T>
void AddObject(const std::string& key, const T object) {
auto ptr = make_shared<B<MyClass>>(std::move(object));
mSharedPtrMap.insert(pair<string, shared_ptr<A>>("key", ptr));
}
// ...
private:
class A {
public:
virtual ~A() = default;
};
template<typename T>
class B : public A {
public:
explicit B(const T& t) : item(t) {}
const T item;
};
map<string, shared_ptr<A>> mSharedPtrMap;
};
int main() {
MyClass m(1);
MultipleTypeMap multiMap;
multiMap.AddObject("test", m);
MyClass n(1);
MultipleTypeMap multiMap2;
multiMap2.AddObject("test", n);
if (multiMap == multiMap2) {
cout << "Equal" << endl;
}
return 0;
}
应如何编写MultipleTypeMap的泛型==运算符,以便通过检查lhs和rhs对象是否具有相同数量的键,相同键和相同对象来比较mSharedPtrMap的内容,其中相同意味着==键/对象的运算符计算是否为真?
答案 0 :(得分:2)
如果您键入擦除(后来又不知道以前存储的是哪种类型),则所有功能都必须由基类接口提供。因此,我们需要在operator==
中实现一个A
中的虚拟B
。
这是一个实现:
class MultipleTypeMap {
public:
template <typename T>
void AddObject(const std::string& key, T object) {
auto ptr = std::make_unique<B<T>>(std::move(object));
mMap.emplace(key, std::move(ptr));
}
// ...
bool operator==(const MultipleTypeMap& other) const
{
// Sizes must be equal.
if (mMap.size() != other.mMap.size())
return false;
// Sizes are equal, check keys and values in order.
auto itOther = other.mMap.begin();
for (auto it = mMap.begin(); it != mMap.end(); ++it, ++itOther)
{
if (it->first != itOther->first)
return false;
if (*it->second != *itOther->second)
return false;
}
// No differences found.
return true;
}
bool operator!=(const MultipleTypeMap& rhs) const { return !(*this == rhs); }
private:
class A {
public:
virtual ~A() = default;
virtual bool operator==(const A& other) const = 0;
bool operator!=(const A& other) const { return !(*this == other); }
};
template<typename T>
class B : public A
{
public:
explicit B(const T& t) : item(t) {}
bool operator==(const A& other) const override
{
const B<T>* otherB = dynamic_cast<const B<T>*>(&other);
// If the cast fails, types are different.
if (!otherB)
return false;
// Note: The above is probably slow, consider storing (on construction)
// and checking typeids instead.
// Check item equality.
return item == otherB->item;
}
const T item;
};
std::map<std::string, std::unique_ptr<A>> mMap;
};
注意:我并没有解决原始代码中的所有不一致问题。 (您想移动或复制构建T
吗?为什么在const
比较运算符不是MyClass
的情况下存储const
对象?)