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

将static_cast转换后的CRTP派生类方法作为模板参数实现记忆化

CRTP接口记忆化封装解决方案

该需求完全可以实现,现有代码的报错是实现细节不符合C++语法规范导致的,修正如下:

核心错误点

  1. 成员函数指针类型不匹配:你声明的模板参数RetType (*Method)(const dVec&)是普通函数指针类型,而&Derived::operator()是派生类的非静态成员函数,对应指针类型应为RetType (Derived::*Method)(const dVec&)(若成员函数带const修饰则末尾需加const)。
  2. 非静态成员不支持auto推导:C++标准禁止类的非静态数据成员用auto声明类型,必须显式指定完整类型。
  3. 缓存判断逻辑颠倒:现有代码中参数与缓存值近似相等时才重新计算,完全失去了缓存意义,应为不相等时才更新缓存。
  4. 派生类存储方式错误:memoize类中直接存储Derived对象会导致对象切片,应该存储派生类指针。

修正后实现代码

memoize类实现

template <typename RetType, typename Derived, RetType (Derived::*Method)(const dVec&) const>
class memoize
{
public:
    constexpr memoize(Derived* derived_ptr)
        : derived_ptr_(derived_ptr) 
        {}
    
    RetType operator()(const dVec& x)
    {
        if (!x.isApprox(mem_x_))
        {
            mem_x_ = x;
            mem_data_ = (derived_ptr_->*Method)(x);
        }
        return mem_data_;
    }

private:
    Derived* derived_ptr_;
    RetType mem_data_{};
    dVec mem_x_{};
};

CRTP基类中使用示例

template <typename Derived>
class YourCRTPInterface
{
// 私有记忆化成员,显式指定类型,不可用auto
private:
    memoize<scalar, Derived, &Derived::operator()> mem_operator;

public:
    // 构造函数中初始化记忆器,传入派生类指针
    YourCRTPInterface() : mem_operator(static_cast<Derived*>(this)) {}

    inline scalar operator()(const dVec& x)
    {
        return mem_operator(x);
    }

    // 其他接口方法同理实现
};

通用化扩展方案(C++17及以上)

如果要支持任意参数类型、任意成员函数的记忆化,可以借助C++17的auto非类型模板参数简化模板声明,无需手动指定返回值和参数类型:

template <auto Method, typename Derived>
class memoize
{
    // 内部用decltype自动推导Method的签名,实现通用逻辑
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 19:57:02