将static_cast转换后的CRTP派生类方法作为模板参数实现记忆化
CRTP接口记忆化封装解决方案
该需求完全可以实现,现有代码的报错是实现细节不符合C++语法规范导致的,修正如下:
核心错误点
- 成员函数指针类型不匹配:你声明的模板参数
RetType (*Method)(const dVec&)是普通函数指针类型,而&Derived::operator()是派生类的非静态成员函数,对应指针类型应为RetType (Derived::*Method)(const dVec&)(若成员函数带const修饰则末尾需加const)。 - 非静态成员不支持auto推导:C++标准禁止类的非静态数据成员用auto声明类型,必须显式指定完整类型。
- 缓存判断逻辑颠倒:现有代码中参数与缓存值近似相等时才重新计算,完全失去了缓存意义,应为不相等时才更新缓存。
- 派生类存储方式错误: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
相关产品推荐
相关产品推荐

