比较 unique_ptr 的地图

Compare maps of unique_ptr

是否可以比较包含 std::unique_ptr 的两个地图?

在我的具体情况下,我想比较两个包含 std::unique_ptr 元组的映射(std::tuple 部分与问题无关,但我认为考虑引起的复杂性很重要通过在手动实现最基本的操作(如比较)时使用异构类型)。

class MyObject
{
public:
    bool operator==(const MyObject& other) const
    {
        return member1 == other.member1;
    }

    bool operator!=(const MyObject& other) const;

private:
    std::string member1 = "specific string";
};

TEST(General, CompareMapOfTuplesOfUniquePtrs)
{
    using MyType = std::map<int32_t, std::tuple<int32_t, std::unique_ptr<MyObject>>>;

    MyType map1;
    MyType map2;

    map1.insert({ 1, std::make_tuple(2, std::make_unique<MyObject>()) });
    map2.insert({ 1, std::make_tuple(2, std::make_unique<MyObject>()) });

    ASSERT_EQ(map1, map2);
}

很明显,当我运行上面的测试(使用Google测试)时,测试会失败,因为比较的是地址,而不是值(为此提供了 operator==operator!=)。

Actual: { (1, (2, 4-byte object <B8-BF 86-01>)) }
Expected: map1
Which is: { (1, (2, 4-byte object <A0-BC 86-01>)) }
[FAILED]

我可以手动迭代每一对并取消引用每个对象,但我想知道是否有针对 unique_ptr 的更标准化的解决方案,因为它是一个基本构造。

我能想到的最标准的解决方案就是为该元组定义自己的相等运算符:

bool operator==( const std::tuple<int32_t, std::unique_ptr<MyObject>> & a,
                 const std::tuple<int32_t, std::unique_ptr<MyObject>> & b )
{
    return std::get<0>(a) == std::get<0>(b) && *std::get<1>(a) == *std::get<1>(b);
}

这个例子对你来说可能已经足够了,除非你还想处理 nullptr。如果您对其他元组使用相同的模式,那么对其进行模板化可能是有意义的:

template < class A, class B >
bool operator==( const std::tuple<A, std::unique_ptr<B>> & a,
                 const std::tuple<A, std::unique_ptr<B>> & b )
{
    return std::get<0>(a) == std::get<0>(b) && *std::get<1>(a) == *std::get<1>(b);
}