2016-09-26 93 views
3

假设我们有一个维护一组元素的数据结构Foo。应该可以根据需要将属性与元素相关联。这些属性应该分别存储在一个单独的向量中。我们通过可变参数模板来实现这一点:如何在同一个可变参数模板的不同实例之间进行转换?

#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. 
}; 

现在,我想用下面的语义的转换操作符:

Foo<AttrB, AttrC> bar = foo; // bar.AttrB::values should be a copy of foo.AttrB::values. 

这仅仅是一个例子。通常,转换运算符应该能够将具有任意属性的Foo转换为具有任意属性的另一个Foo。应该复制与Foo相关的属性。不与两者关联的属性可以保持默认。但是,我不知道如何实现它。

template <typename ...OthersAttrs> 
    operator Foo<OthersAttrs...>() const { 
    // ...? 
    } 
+1

你是做什么关于与关联的属性目标但不是来源? – merlin2011

+0

现在不重要。也许他们的价值被设定为某种默认值,或许他们的价值是简单的未定义的。 – user1494080

+0

@ user1494080这是非常重要的:你想从'foo'复制初始化后'bar'是什么? – Barry

回答

5

我们可以做一堆独立的决定。首先,让我们添加一个构造函数,以便我们可以构建从它的属性成分Foo

Foo(Attrs const&... attrs) 
: Attrs(attrs)... 
{ } 

接下来,为每个属性在Others,我们要么垂头丧气this到合适的类型,如果可能,或者返回一个默认构造的一个否则:

template <typename... Others> 
operator Foo<Others...>() const { 
    return {get_attr<Others>(this)...}; 
} 

其中:

template <class T> 
T const& get_attr(T const* v) const { 
    return *v; 
} 

template <class T> 
T get_attr(...) const { 
    return T{}; 
} 
2

大纲我能想到的:

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 
{ 

} 

这里的窍门是通过属性去属性。
如果rv具有该属性,则将选择第一个重载并将其复制。
否则,第二次重载将被选择,将无所事事。

相关问题