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

C++14环境下实现持有A/B引用的TargetProxy以统一Sender虚send接口

TargetProxy实现方案

我们可以通过「类型标签+常量指针存储」的方式实现完全兼容C++14标准的TargetProxy,无第三方依赖,同时支持Google Mock的等值匹配断言,具体实现如下:

完整TargetProxy代码

class TargetProxy {
public:
    // 支持隐式构造,上层传A/B时可自动转换,无需修改业务调用代码
    TargetProxy(const A& a) : type_(Type::kA), ptr_(&a) {}
    TargetProxy(const B& b) : type_(Type::kB), ptr_(&b) {}

    // 类型判断接口,供虚函数实现逻辑区分地址类型使用
    bool isA() const { return type_ == Type::kA; }
    bool isB() const { return type_ == Type::kB; }

    // 安全取值接口,调用前需先通过isA/isB确认对应类型
    const A& getA() const { return *static_cast<const A*>(ptr_); }
    const B& getB() const {
        if (isA()) {
            // 利用A可转换为B的特性返回对应实例
            return static_cast<B>(getA());
        }
        return *static_cast<const B*>(ptr_);
    }

    // 重载==运算符,适配Google Mock的Eq匹配规则
    bool operator==(const TargetProxy& rhs) const {
        if (type_ == rhs.type_) {
            return type_ == Type::kA ? (getA() == rhs.getA()) : (getB() == rhs.getB());
        }
        // 跨类型比较时统一转成B再对比,可根据需求去掉该逻辑
        return getB() == rhs.getB();
    }

    // 支持直接和A/B实例做等值比较
    bool operator==(const A& rhs) const {
        return isA() && getA() == rhs;
    }
    bool operator==(const B& rhs) const {
        return getB() == rhs;
    }

private:
    enum class Type {
        kA,
        kB
    };
    Type type_;
    const void* ptr_;
};

// 补充全局==重载,支持A/B实例在左的比较场景,适配Eq参数顺序不固定的情况
inline bool operator==(const A& lhs, const TargetProxy& rhs) {
    return rhs == lhs;
}
inline bool operator==(const B& lhs, const TargetProxy& rhs) {
    return rhs == lhs;
}

Sender类改造示例

对外API完全不变,业务侧无感知,底层合并为统一虚接口:

class Sender{
public:
    // 原有对外接口保留,仅修改内部实现
    template<typename TReq>
    void send(const A& target, TReq req) {
        send(TargetProxy(target), make_request(std::move(req)));
    }

    template<typename TReq>
    void send(const B& target, TReq req) {
        send(TargetProxy(target), make_request(std::move(req)));
    }

protected:
    // 合并后的统一虚接口
    virtual void send(const TargetProxy& target, MessageProxy message);
};

GMock适配说明

因为已经完整重载了所有等值比较场景的==运算符,你要求的测试用例可以直接正常使用:

EXPECT_CALL(mock, send(Eq(A{}), Message{}))...
EXPECT_CALL(mock, send(Eq(B{}), OtherMessage{}))...

注意事项

  • TargetProxy仅做引用透传,不持有地址对象的所有权,不要长期持有TargetProxy实例避免悬空引用,当前仅在send调用栈内使用是完全安全的
  • 如果不需要跨类型等值比较,可以去掉跨类型转B对比的逻辑,减少不必要的B实例构造开销

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 05:24:03