2016-09-26 9 views
3

要素のセットを保持するデータ構造Fooがあるとします。必要に応じて要素に属性を関連付けることが可能でなければなりません。属性は別々のベクタに格納する必要があります。私たちは、可変長引数テンプレートを用いてこれを実装:同じvariadicテンプレートの異なるインスタンス間の変換方法は?

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

これが唯一の例である:

#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を任意の属性を持つ別のFooに変換できる必要があります。 Fooに関連付けられた属性をコピーする必要があります。両方に関連付けられていない属性は、デフォルトのままにすることができます。しかし、私はそれをどのように実装するのか分かりません。私は考えることができる

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

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

ターゲットではありますが、ソースではありませんか? – merlin2011

+0

現在は重要ではありません。おそらく、その値はデフォルト値に設定されているかもしれません。おそらくその値は単純に定義されていません。 – user1494080

+0

@ user1494080これはかなり重要です: 'foo'からのコピー初期化の後に' bar'をしたいのは何ですか? – Barry

答えて

5

私たちはたくさんの独立した決定をすることができます。まず、私たちはその属性成分からFooを構築することができるようにのは、コンストラクタを追加してみましょう。

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

次に、Othersの各属性のため、我々は可能な場合は適切な型にthisダウンキャストのどちらかでしょうか、デフォルトで構築1を返しますそうでない場合:あなたがに関連付けられている属性について何をしますか

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に属性がある場合、最初のオーバーロードが選択され、コピーされます。
それ以外の場合、何もしない2番目のオーバーロードが選択されます。

関連する問題