是否有可能创建一个模板,当专门生成另一个模板时?

时间:2015-06-09 21:43:22

标签: c++ templates

我正在处理一些有两个完全不同的序列化机制的不幸代码。一个使用模板用于看起来像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 <bool> class ArchiveV2serialize_adapter(one)不匹配 - 因为它只是class ArchiveV1。但是serialize_adapter只能采用bool - 它必须采用ArchiveV1参数。

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

2 个答案:

答案 0 :(得分:1)

template <bool> class ArchiveV2可以被视为元函数S: bool -> type。你需要什么可以看作是一个元函数A: type -> S,即一个&#34; metametafunction&#34;。返回元函数的元函数可以通过成员模板编写:

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

        ArchiveV1& one;
    };
};

注意&#34;普通&#34;元函数:

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
}

答案 1 :(得分:0)

反过来说:写一个serialize_adaptor,它采用更专业的类型 - 这是一个源自带有布尔参数的模板的类 - 并将其转换为一般类型。< / p>

示例:

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时,您应该为这种情况添加一些其他特化。