【问题标题】:Is it possible to create a template which, when specialized, yields another template?是否可以创建一个模板,当专门化时,它会产生另一个模板?
【发布时间】:2015-06-09 21:43:21
【问题描述】:

我正在处理一些不幸的代码,它有两种完全不同的序列化机制。一个使用类似于template <class Archive> void serialize_v1(Archive& a) 的存档模板,而另一个使用template <template <bool> class Archive> void serialize_v2(Archive<false>& a)。第一个重载一个操作符进行序列化,如a % foo 进行序列化,而第二个使用归档上​​的方法,如a.proc_int(foo)

我正在尝试在两者之间编写一个适配器,这样我就不必一直编写两个序列化函数。理想情况下,我会有类似的东西:

template <class ArchiveV1>
class serialize_adapter
{
    serialize_adapter(ArchiveV1& one) : one(one) { }; 

    // functions for v2 serialization
    void proc_int(int x) {
        one % x;
    }

    ArchiveV1& one;
}

template <class ArchiveV1>
void serialize_v1(ArchiveV1& one)
{
    serialize_v2(serialize_adapter(one)); // calls adapter's v2 funcs
}

但是,serialize_v2 采用 template &lt;bool&gt; class ArchiveV2,而 serialize_adapter(one) 不匹配 - 因为它只是一个 class ArchiveV1。但是serialize_adapter 不能只使用bool - 它必须使用ArchiveV1 参数。

似乎我需要创建一个专门针对Archive 类型的模板,这会生成一个专门针对bool 的模板,然后我可以将其传递给serialize_v2。我该如何去做,或者如果这是错误的方法,那么正确的方法是什么?

【问题讨论】:

    标签: c++ templates


    【解决方案1】:

    template &lt;bool&gt; class ArchiveV2 可以看作是一个元函数S: bool -&gt; type。你需要的可以看成一个元函数A: type -&gt; S,也就是一个“元元函数”。可以通过成员模板编写返回元函数的元函数:

    template<class ArchiveV1>
    struct serialize_adapter
    {
        template<bool>
        struct result
        {
            void proc_int(int x) {
                one % x;
            }
    
            ArchiveV1& one;
        };
    };
    

    注意与“普通”元函数的类比:

    template<class X>
    struct metafun
    {
        using result = /* some type */;
    };
    

    result 通常被称为type

    然后适配器函数可以写成:

    template <class ArchiveV1>
    void serialize_v1(ArchiveV1& one)
    {
        using adapter = serialize_adapter<ArchiveV1>::template result<false>;
        serialize_v2(adapter{one}); // calls adapter's v2 funcs
    }
    

    【讨论】:

    • 如果您需要更多这些适配器类,您还可以通过继承 + CRTP 引入一个 dummy bool。
    【解决方案2】:

    反过来做:编写一个serialize_adaptor,它采用更专业的类型——即源自具有布尔参数的模板的类——并将其转换为通用类型。

    例子:

    template <template<bool> class ArchiveV2>
    class serialize_adapter
    {
        serialize_adapter(ArchiveV2<false>& one) : one(one) { }; 
    
        // functions for v1 serialization
        void operator%(int x) {
            one.proc_int(x);
        }
    
        ArchiveV2<false>& one;
    }
    
    template <template<typename> class ArchiveV2>
    void serialize_v2(ArchiveV2<false>& one)
    {
        serialize_v1(serialize_adapter(one)); // calls adapter's v1 funcs
    }
    

    在这里,您可能应该为布尔参数为true 的情况添加一些进一步的特化。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多