[英]How to convert between different instantiations of the same variadic template?
Assume we have a data structure Foo that maintains a set of elements. 假设我们有一个维护一组元素的数据结构Foo。 It should be possible to associate attributes with the elements as needed.
应该可以根据需要将属性与元素相关联。 The attributes should be stored in a separate vector each.
属性应分别存储在单独的向量中。 We implement this by means of variadic templates:
我们通过可变参数模板实现这一点:
#include <vector>
template <typename ...Attrs>
struct Foo : public Attrs... {
Foo(int n = 0) {
using PackExpansionT = int[];
PackExpansionT{0, (Attrs::values.resize(n), 0)...};
}
};
struct AttrA { std::vector<int> values; };
struct AttrB { std::vector<float> values; };
struct AttrC { std::vector<double> values; };
int main() {
Foo<AttrA, AttrB> foo; // Maintains set of elements with two attributes each.
};
Now, I want a conversion operator with the following semantics: 现在,我想要一个具有以下语义的转换运算符:
Foo<AttrB, AttrC> bar = foo; // bar.AttrB::values should be a copy of foo.AttrB::values.
This is only an example. 这只是一个例子。 In general, the conversion operator should be able to convert a
Foo
with arbitrary attributes into another Foo with arbitrary attributes. 通常,转换运算符应该能够将具有任意属性的
Foo
转换为具有任意属性的另一个Foo。 Attributes associated with both Foo
s should be copied. 应复制与两个
Foo
相关的属性。 Attributes not associated with both can be left defaulted. 与两者无关的属性可以保留默认值。 However, I have no idea how to implement it.
但是,我不知道如何实现它。
template <typename ...OthersAttrs>
operator Foo<OthersAttrs...>() const {
// ...?
}
We can just make a bunch of independent decisions. 我们可以做出一堆独立的决定。 First, let's add a constructor so that we can construct
Foo
from its attribute constituents: 首先,让我们添加一个构造函数,以便我们可以从其属性成分构造
Foo
:
Foo(Attrs const&... attrs)
: Attrs(attrs)...
{ }
Next, for each attribute in Others
, we will either downcast this
to the appropriate type if possible or return a default-constructed one otherwise: 接下来,对于每个属性
Others
,我们要么垂头丧气this
为适当的类型如果可能的话,或者返回一个缺省构造一个以其他方式:
template <typename... Others>
operator Foo<Others...>() const {
return {get_attr<Others>(this)...};
}
where: 哪里:
template <class T>
T const& get_attr(T const* v) const {
return *v;
}
template <class T>
T get_attr(...) const {
return T{};
}
An outline I can think of: 我能想到的大纲:
template <typename ...OthersAttrs>
operator Foo<OthersAttrs...>() const
{
Foo<OthersAttrs...> rv(GetNSomehow());
(int[]){(CopyAttr<Attrs>(&rv), 0)...};
return rv;
}
template<typename Attr>
void CopyAttr(Attr *rv) const // Overload A
{
rv->values = ((const Attr*)this)->values;
}
template<typename Attr>
void CopyAttr(...) const // Overload B
{
}
The trick here is to go attribute by attribute. 这里的技巧是逐个属性。
If rv
has the attribute the first overload will be chosen and it will be copied. 如果
rv
具有该属性,则将选择第一个重载并将其复制。
Otherwise the second overload would be chosen that will do nothing. 否则,将选择不执行任何操作的第二个过载。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.