递归模板定义

时间:2011-06-16 11:11:54

标签: c++ templates recursion definition

我有一个递归模板定义(我只是编造了这个术语)。我认为代码更好地解释了它。

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&lt; 1;

有没有人遇到任何问题?你提出了什么解决方案?

2 个答案:

答案 0 :(得分:7)

这与模板元编程101示例 - 阶乘相同,只是内容稍微复杂一些。

template<int N> struct factorial { enum { value = N * factorial<N-1>::value }; };

你需要相同的解决方案 - 基本案例的专业化。

template<> struct factorial<1> { enum { value = 1 }; };

你的是部分的而不是满的,但它仍然有用。

答案 1 :(得分:2)

添加如下内容:

template<typename X, typename Y>
class NthOrderFunction<X, Y, 1>
    : 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
        {
            return new FlatLine<X, Y>(dom);
        }
};

并从递归案例中删除n == 1个案例。

作为建议,在模板元编程上获取一些书籍或教程等。其中一种基本技术是以这种方式在模板中使用递归。严格来说,这不是元编程,它只是递归模板。本书/教程将解释更多高级技巧的工作原理,在扩展时可以使用这些技巧。

这样做的原因是原始文件仍会将编译时“if”扩展为运行时代码(永远不会被执行)。这段代码取代了一个可以用不存在的代码编译出来的情况,所以没有无限递归的选项。