我有一个递归模板定义(我只是组成了这个术语).我认为代码更好地解释了它.
template<typename X> class Domain { public: X begin; X end; Domain( X _begin,X _end) : begin(_begin),end(_end) { // ... } bool Contains( const X& t) const { // ... } }; template<typename X,typename Y> class IFunction { public: Domain<X> myDomain; public: IFunction( const Domain<X>& dom) : myDomain(dom) { } virtual Y Calc( const X& IV) const = 0; virtual IFunction<X,Y>* GetDerivative() const = 0; }; template<typename X,typename Y,int n> class NthOrderFunction : public IFunction<X,Y> { public: double coeffs[n+1]; public: NthOrderFunction( const Domain<X>& dom,... ) : IFunction(dom) { } virtual Y Calc( const X& IV) const { // temporary compile solution return Y(); } virtual IFunction<X,Y>* GetDerivative() const { if ( n > 1 ) { return new NthOrderFunction<X,Y,n-1>(dom,...); } return new FlatLine<X,Y>(dom); } };
我拿出了很多继承和其他关系来保持它的可读性,简单性和神秘性.因此,编辑代码时可能会遇到新的拼写错误,但请忽略它.代码已经运行了好几年,我唯一的问题就是我要指出的问题.
我最近添加了一个“GetDerivative”函数,它在NthOrderFunction类中的实现给了我一些问题.我知道模板类是在编译之前定义的,但是在预处理之后定义.因此,我无法看到如何使此功能工作.每个带模板参数n的NthOrderFunction都需要带模板参数n-1的NthOrderFunction.你可以看到这是一个问题.问题是,即使n在使用中永远不会是负面的,但我没有做任何编码,也会说服“模板定义引擎”不打扰n< 1; 有没有人遇到任何问题?你提出了什么解决方案?
解决方法
添加如下内容:
template<typename X,typename Y> class NthOrderFunction<X,1> : public IFunction<X,Y>* GetDerivative() const { return new FlatLine<X,Y>(dom); } };
并从递归案例中删除n == 1个案例.
作为建议,在模板元编程上获得一些书籍或教程等.其中一种基本技术是以这种方式在模板中使用递归.严格来说,这不是元编程,它只是递归模板.本书/教程将解释更多高级技巧的工作方式,在扩展时可以使用这些技巧.
这样做的原因是原始的仍然会将编译时“if”扩展为运行时代码(永远不会被执行).这段代码替换了一个可以编译出来的情况,其中一个不存在,所以没有无限递归的选项.