You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否编写通用深度比较函数?对比未重载operator==的类对象

可以编写这样的通用深度比较函数吗?

答案是可以实现,但需要解决几个关键问题,同时存在一定局限性,下面逐一拆解:

核心前提:成员访问权限

你给出的Class1和Class2成员默认是私有(private)的,模板函数Compare无法直接访问这些成员。解决方式有两种:

  • 将类的成员改为公有(public)
  • 在类中声明Compare模板为友元

比如修改Class1:

class Class1 {
    int i;
    int *pi;
    // 声明友元,让Compare能访问私有成员
    template<typename T>
    friend bool Compare(T obj1, T obj2);
};

深度比较的实现思路

要实现深度比较,需要针对不同类型的成员做差异化处理:

  • 对于基本数据类型(int、char等):直接用==比较
  • 对于指针类型:先判断指针是否都为空(两个空指针视为相等),若非空则解引用后递归比较指向的值
  • 对于自带operator==的类型(比如std::string):直接调用其自身的比较逻辑
  • 对于自定义类类型:递归调用Compare函数比较其内部成员

代码实现示例

利用C++的类型萃取(如std::is_pointer、std::is_fundamental)和SFINAE(替换失败不是错误)实现类型分支:

#include <type_traits>
#include <string>

// 处理自定义类(非指针、非基本类型)
template<typename T>
typename std::enable_if<!std::is_pointer<T>::value && !std::is_fundamental<T>::value, bool>::type
Compare(const T& obj1, const T& obj2) {
    // 手动适配每个自定义类的成员比较逻辑
    if constexpr (std::is_same_v<T, Class1>) {
        return obj1.i == obj2.i && Compare(obj1.pi, obj2.pi);
    }
    else if constexpr (std::is_same_v<T, Class2>) {
        return obj1.c == obj2.c && Compare(obj1.pc, obj2.pc) && Compare(obj1.ps, obj2.ps);
    }
    // 其他自定义类需在此添加分支
    else {
        static_assert(std::is_void_v<T>, "Unsupported type for Compare");
        return false;
    }
}

// 处理指针类型
template<typename T>
typename std::enable_if<std::is_pointer<T>::value, bool>::type
Compare(const T& ptr1, const T& ptr2) {
    if (!ptr1 && !ptr2) return true;
    if (!ptr1 || !ptr2) return false;
    return Compare(*ptr1, *ptr2);
}

// 处理基本数据类型
template<typename T>
typename std::enable_if<std::is_fundamental<T>::value, bool>::type
Compare(const T& val1, const T& val2) {
    return val1 == val2;
}

// 复用std::string自带的比较逻辑
template<>
bool Compare(const std::string& s1, const std::string& s2) {
    return s1 == s2;
}

// 自定义类声明(带友元)
class Class1 {
    int i;
    int *pi;
    template<typename T>
    friend bool Compare(const T& obj1, const T& obj2);
};

class Class2 {
    char c;
    char *pc;
    std::string *ps;
    template<typename T>
    friend bool Compare(const T& obj1, const T& obj2);
};

// 使用示例
int main() {
    Class1 a1, b1;
    // 初始化逻辑...
    bool c1 = Compare(a1, b1);

    Class2 a2, b2;
    // 初始化逻辑...
    bool c2 = Compare(a2, b2);
    return 0;
}

关键局限性

  • 无法完全自动适配所有自定义类:上述实现需要手动为每个自定义类添加成员比较分支,除非使用C++20及以后的实验性反射特性,否则无法自动遍历类的所有成员。
  • 循环引用风险:如果类中存在指向自身的指针(如Class1包含Class1*成员),递归比较会导致栈溢出。
  • 未初始化指针的未定义行为:若指针未初始化,解引用会触发UB,需确保传入对象已正确初始化。
  • 智能指针需额外处理:如果类中使用std::unique_ptr、std::shared_ptr等智能指针,需单独适配比较逻辑(比如比较指向的对象而非控制块地址)。

内容的提问来源于stack exchange,提问作者Pietro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 00:33:11