C++模板参数推导问题:简化Integrator类实例化
问题描述
现有C++代码如下:
#include <array> template <size_t StateSize, typename VariableType> class DifferentialEquation { public: using StateType = std::array<VariableType, StateSize>; using Var = VariableType; // ... }; template <size_t StateSize, typename VariableType> class RungeKutta4 { // ... }; template< template<size_t, class> class IntegratorStrategy, class VariableType, size_t StateSize > class Integrator { public: using DE = DifferentialEquation<StateSize, VariableType>; using Strategy = IntegratorStrategy<StateSize, VariableType>; public: Integrator(DE de) : m_de(de) {} // ... private: DE m_de; Strategy m_strategy; };
其中:
DifferentialEquation表示微分方程,StateType是std::array类型的状态向量RungeKutta4是积分策略类Integrator依赖DifferentialEquation完成积分计算
当前可以通过以下代码成功实例化:
DifferentialEquation<2, double> deq; Integrator<RungeKutta4, double, 2> integrator(deq);
但希望消除模板参数冗余——double和2已经在DifferentialEquation中指定,希望简化为:
DifferentialEquation<2, double> deq; Integrator<RungeKutta4> integrator(deq);
尝试的推导指南未生效:
template< template<size_t, class> class IntegratorStrategy, class VariableType, size_t StateSize > Integrator(DifferentialEquation<StateSize, VariableType>) -> Integrator< IntegratorStrategy<StateSize, VariableType>, VariableType, StateSize >;
编译报错(Visual Studio):
IntegrationTest.cpp(44): error C2955: 'Integrator': use of class template requires template argument list IntegrationTest.cpp(23): note: see declaration of 'Integrator' IntegrationTest.cpp(44): error C3200: 'IntegratorStrategy<StateSize,VariableType>': invalid template argument for template parameter 'IntegratorStrategy', expected a class template IntegrationTest.cpp(44): error C2955: 'Integrator': use of class template requires template argument list IntegrationTest.cpp(23): note: see declaration of 'Integrator' IntegrationTest.cpp(44): error C2955: 'Integrator': use of class template requires template argument list IntegrationTest.cpp(23): note: see declaration of 'Integrator' IntegrationTest.cpp(44): error C2639: trailing return type 'Integrator' of deduction guide should be a specialization of 'Integrator' ninja: build stopped: subcommand failed.
解决方案
方法1:修正模板推导指南
原推导指南的核心错误是:将实例化后的策略类(IntegratorStrategy<StateSize, VariableType>)传给了Integrator的第一个模板参数,但Integrator的第一个参数是模板模板参数,需要接收未实例化的模板(比如RungeKutta4)。
正确的推导指南应直接传递模板模板参数,从构造函数参数中自动推导VariableType和StateSize:
template< template<size_t, class> class IntegratorStrategy, typename VariableType, size_t StateSize > Integrator(DifferentialEquation<StateSize, VariableType>) -> Integrator<IntegratorStrategy, VariableType, StateSize>;
修改后,Integrator<RungeKutta4> integrator(deq);即可正常编译——编译器会从deq的类型自动推导VariableType=double和StateSize=2,结合指定的IntegratorStrategy=RungeKutta4生成正确实例。
方法2:调整Integrator模板参数顺序(可选优化)
若想让模板参数逻辑更清晰,可将可推导的参数放在后面:
template< template<size_t, class> class IntegratorStrategy, size_t StateSize, typename VariableType > class Integrator { // 内部代码保持不变 };
配合修正后的推导指南,实例化代码依然可以正常工作,仅优化了参数顺序的可读性。
验证代码
完整可编译示例:
#include <array> template <size_t StateSize, typename VariableType> class DifferentialEquation { public: using StateType = std::array<VariableType, StateSize>; using Var = VariableType; }; template <size_t StateSize, typename VariableType> class RungeKutta4 {}; template< template<size_t, class> class IntegratorStrategy, class VariableType, size_t StateSize > class Integrator { public: using DE = DifferentialEquation<StateSize, VariableType>; using Strategy = IntegratorStrategy<StateSize, VariableType>; public: Integrator(DE de) : m_de(de) {} private: DE m_de; Strategy m_strategy; }; // 正确的推导指南 template< template<size_t, class> class IntegratorStrategy, typename VariableType, size_t StateSize > Integrator(DifferentialEquation<StateSize, VariableType>) -> Integrator<IntegratorStrategy, VariableType, StateSize>; int main() { DifferentialEquation<2, double> deq; Integrator<RungeKutta4> integrator(deq); // 编译通过 return 0; }
内容的提问来源于stack exchange,提问作者Jepessen
相关产品推荐
相关产品推荐

