递归模板定义

发布于 2024-11-15 11:54:58 字数 1891 浏览 0 评论 0原文

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

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 < n < n 的实例。 1;

有人遇到过这方面的问题吗?你想出了什么解决方案?

I have a recursive template definition (I just made up that term). I think code explains it better.

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);
        }
};

I took out a lot of inheritance and other relations to keep it readable, simple and mysterious. So a new typo might have snuck in while editing the code, but please ignore it. The code has worked fine for years, the only problem I have is the one I'm going to point out.

I recently added a "GetDerivative" function, and it's implementation in the NthOrderFunction class is giving me problems. I know that template classes are defined before compilation but after the preprocessing. As such, I can't see how to bring this functionality ever to work. Every NthOrderFunction with template parameter n, requires a NthOrderFunction with template parameter n-1. You can see that this is a problem. The thing is, even though n will never be negative in use, no amount of coding I do, will convince the "template definition engine" to not bother with instances of n < 1;

has anyone ever had any problems with this? And what solutions did you come up with?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

嘿嘿嘿 2024-11-22 11:54:58

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

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

您需要相同的解决方案——针对基本案例的专业化。

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

你的将是部分的而不是完整的,但它仍然可以工作。

This is the same as the template metaprogramming 101 example- factorial, just the content is somewhat more complex.

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

And you need the same solution- a specialization for the base case.

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

Yours would be partial rather than full, but it would still work.

超可爱的懒熊 2024-11-22 11:54:58

添加类似:

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”扩展为运行时代码(永远不会被执行)。该代码用不存在的情况替换了可以编译出来的一种情况,因此没有无限递归的选项。

Add something like:

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);
        }
};

and remove the n==1 case from your recursion case.

As an advice, get some book or tutorial or such on template metaprogramming. One of the base techniques is using recursion in templates in this fashion. This strictly speaking isn't metaprogramming yet, it's just recursive templates. The book/tutorial will explain how more advanced tricks work which you can use to your benefit when expanding on this.

The reason this works is that the original would still expand the compile-time "if" to runtime code (that would just never be executed). This code replaces the one case where it could be compiled out with one where it isn't present, so there's no option for infinite recursion.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文