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

基于基类重载函数推导sumClass模板参数T(C++20)

问题描述

现有如下C++代码:

class intClass {
public:
    virtual ~intClass() = default;

    virtual int sum(int a, int b) const = 0;
};

class doubleClass {
public:
    virtual ~doubleClass() = default;

    virtual double sum(double a, double b) const = 0;
};

template<typename T, typename C>
class sumClass : public C {
public:
    T sum(T a, T b) const override {
        return a + b;
    }
};

int main() {
    sumClass<int, intClass> intSum;
    sumClass<double, doubleClass> doubleSum;
    return 0;
}

已知intClass和doubleClass不可修改,需要移除sumClass的模板参数T,能否基于基类中sum函数的签名自动推导T?允许使用C++20标准,最终期望的main函数如下:

int main() {
    sumClass<intClass> intSum;
    sumClass<doubleClass> doubleSum;
    return 0;
}
解决方案

可以实现,核心思路是用类型萃取从基类的sum函数签名里提取出目标类型T,再重构sumClass模板。

1. 实现类型萃取工具

我们需要一个工具来从基类的sum成员函数指针中提取出类型T:

#include <type_traits>

// 基础模板,用于匹配成员函数指针
template<typename FuncPtr>
struct extract_sum_type_from_func_ptr;

// 特化模板,匹配签名为 T (C::*)(T, T) const 的成员函数
template<typename C, typename T>
struct extract_sum_type_from_func_ptr<T (C::*)(T, T) const> {
    using type = T;
};

// 封装成易用的类型别名
template<typename C>
using sum_type = typename extract_sum_type_from_func_ptr<decltype(&C::sum)>::type;

这段代码的作用是:通过decltype(&C::sum)获取基类sum函数的指针类型,再通过模板特化直接提取出其中的T类型(也就是返回值和参数的类型)。

2. 重构sumClass模板

现在把sumClass改成只接受基类C作为模板参数,内部用sum_type<C>替代原来的T:

template<typename C>
class sumClass : public C {
public:
    using T = sum_type<C>;
    T sum(T a, T b) const override {
        return a + b;
    }
};

完整可运行代码

#include <type_traits>

class intClass {
public:
    virtual ~intClass() = default;
    virtual int sum(int a, int b) const = 0;
};

class doubleClass {
public:
    virtual ~doubleClass() = default;
    virtual double sum(double a, double b) const = 0;
};

// 类型萃取工具
template<typename FuncPtr>
struct extract_sum_type_from_func_ptr;

template<typename C, typename T>
struct extract_sum_type_from_func_ptr<T (C::*)(T, T) const> {
    using type = T;
};

template<typename C>
using sum_type = typename extract_sum_type_from_func_ptr<decltype(&C::sum)>::type;

// 重构后的sumClass
template<typename C>
class sumClass : public C {
public:
    using T = sum_type<C>;
    T sum(T a, T b) const override {
        return a + b;
    }
};

int main() {
    sumClass<intClass> intSum;
    sumClass<doubleClass> doubleSum;
    
    // 测试调用,验证功能正常
    int result1 = intSum.sum(3, 5); // 结果为8
    double result2 = doubleSum.sum(2.3, 4.7); // 结果为7.0
    return 0;
}

额外优化(C++20特性)

如果想要在编译期就确保传入的基类符合要求,可以用C++20的concept做约束:

template<typename C>
concept HasValidSumFunc = requires(const C& obj, sum_type<C> a, sum_type<C> b) {
    { obj.sum(a, b) } -> std::same_as<sum_type<C>>;
};

// 只有符合约束的基类才能被传入sumClass
template<HasValidSumFunc C>
class sumClass : public C {
public:
    using T = sum_type<C>;
    T sum(T a, T b) const override {
        return a + b;
    }
};

这样如果传入的基类没有符合要求的sum函数,编译器会直接报错,提前发现问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 13:59:52