我正在处理一些有两个完全不同的序列化机制的不幸代码。一个使用模板用于看起来像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 ArchiveV2
,serialize_adapter(one)
不匹配 - 因为它只是class ArchiveV1
。但是serialize_adapter
只能采用bool
- 它必须采用ArchiveV1
参数。
似乎我需要创建一个专门用于Archive
类型的模板,这会产生一个专门用于bool
的模板,然后我可以将其传递给serialize_v2
。我怎么能这样做,或者如果这是错误的方法,那么正确的做法是什么?
答案 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
时,您应该为这种情况添加一些其他特化。