爱意满满的作品展示区。
geelaw

C++ 成语运用到 C#: CRTP (curiously recurring template pattern) 的应用,以及实现非类型泛型参数

  •  
  •   geelaw ·
    GeeLaw · Aug 3, 2017 · 3064 views
    This topic created in 3260 days ago, the information mentioned may be changed or developed.

    这篇帖子翻译自 这篇博文

    转到 C♯ 上写密码学代码,C♯ 泛型比 C++ 模板的限制多很多,比如 对于泛型参数,不能使用(算术)运算符。这导致类似

    template <unsigned p>
    struct Z
    {
        // Z/pZ 这个环的实现。
    };
    
    template <typename TRing>
    struct Foo
    {
        /* TRing 是一个环的类型,可以当成黑箱
         */
    
        struct AffineTransform
        {
            TRing k, b;
            TRing operator () (TRing x) const
            {
                return k * x + b;
            }
        };
    
        static std::function<TRing(TRing)>
        CreateAffineTransform(TRing k, TRing b)
        {
            AffineTransform aff;
            aff.k = k;
            aff.b = b;
            return aff;
        }
    };
    

    在 C♯ 里不可行。解决方法是 CRTP,让类型自带接口,替代运算符

    另一个问题:C♯ 里面的泛型参数只能是类型,不能是值,这样 Z<p> 的实现看起来就要分开写好几次。

    有两个丑的绕过方法:

    • 用代码生成器;
    • 把 p 做成字段,运算的时候检查,不符合就抛异常。

    第一个方法和 C♯ 本身没有关系了,而且回到原始人时代;第二个方法除了降低运行时效率之外,还会一下子把一个环元素的大小 扩大一倍

    答案是把数值 放进一个类型里面,再借助 CRTP 书写辅助工具,可以让这个基础设施非常好用

    具体请移步 原文

    3 replies    2017-08-04 20:34:43 +08:00
    gnaggnoyil
        1
    gnaggnoyil  
       Aug 4, 2017
    这让我想起了这个帖子:

    https://www.zhihu.com/question/27421302
    geelaw
        2
    geelaw  
    OP
       Aug 4, 2017
    @gnaggnoyil 老技巧了,我后来改写了博文,和现在的翻译总结不太一致了。

    实际上 C# 里面也到处都是 CRTP,比如 IComparable 模式。
    lindexi
        3
    lindexi  
       Aug 4, 2017
    泛型很厉害,至少可以不写工厂
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   2629 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 58ms · UTC 15:42 · PVG 23:42 · LAX 08:42 · JFK 11:42
    ♥ Do have faith in what you're doing.