V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
geelaw
V2EX  ›  分享创造

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

  •  
  •   geelaw ·
    GeeLaw · 2017-08-03 20:31:26 +08:00 · 2240 次点击
    这是一个创建于 2670 天前的主题,其中的信息可能已经有所发展或是发生改变。

    这篇帖子翻译自 这篇博文

    转到 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 条回复    2017-08-04 20:34:43 +08:00
    gnaggnoyil
        1
    gnaggnoyil  
       2017-08-04 01:55:58 +08:00
    这让我想起了这个帖子:

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

    实际上 C# 里面也到处都是 CRTP,比如 IComparable 模式。
    lindexi
        3
    lindexi  
       2017-08-04 20:34:43 +08:00
    泛型很厉害,至少可以不写工厂
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5924 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 03:34 · PVG 11:34 · LAX 19:34 · JFK 22:34
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.