2012-03-02 7 views
2

私は、配列のいくつかの類似の構造、例えば、C++で同様のデータ構造をコピーするテンプレートベースの汎用的な方法はありますか?

map<key1, attr1>; map<key2, attr2>; ..., 

一方、対応して、シリーズ、

// JUST TO SHOW THE IDEA, NOT SYNTAX CORRECT 
class {key_1; attr_1;} array [#]; class {key_2; attr_2;} array [#]; ..., 

とkeyXとkey_Xは同様の構造と同様のattrを共有する一連のを持っています、例えば

struct key1 {int k1;}; class key_1 {int k_1;}; 
struct key2 {int k1; int k2;}; class key_2 {int k_1; int k_2;}; 
    ... 
struct attr1 {int a1; int a2;}; class attr_1 {int a_1; int a_2;}; 

Iは、代入演算子をオーバーロードのような機能を記述するために、他にmap_seriesからのデータを変換すること、およびその逆必要。

ので、代わりにint型によってマップ、キーによってキー、およびint型でそれをマップを行うので、それを行うには、いくつかのテンプレートワイズな方法があり、そのコードは、一般的なこと、またはそれ以上のラインを救いますコードの?これを行うスマートな方法は何でしょうか?

EDIT 1:

残念ながら、1つの制約により、当社のレガシーシステム、構造体間の型convertion、例えばへkey1、key_1はC++プリミティブとしては機能しないので、変換関数も提供する必要があります。

EDIT 2:J.N.に触発

キーおよびattRの変換をgenerlizeする方法

template <class KeyMap, class ValueMap, class KeyArr, class ValueArr> void convert (map<KeyMap, ValueMap>, class {KeyArr, ValueArr} array[]){}; 

:答え、それはのようなものを持つことが可能でしょうか?以下のような

template <class KeyMap, class KeyArr> void convert_key(KeyMap, KeyArr){} 

答えて

3

[OK]をので、我々はこれを持っていると仮定してみましょう:

map<KeyTypeM, ValueTypeM> m1; 
struct Type1 { 
    KeyTypeS Key; 
    ValueTypeS Value; 
}; 

はのは、最初の変換関数を定義してみましょう:

Type1 ConvType1(const KeyTypeM& key, const ValueTypeM& value) 
{ 
    Type1 result; 
    result.Key = f(key); // user dependent 
    result.Value = f(value); // user dependent 

    return result; 
} 

その後、C++で、あなたは配列を返すことはできません。実際には、通常は配列で作業しませんが、人々は通常std::vectorを好んでいます。 (実際に配列が必要な場合は、ポインタを割り当ててポインタを返すか、スマートポインタでラップする必要があります) マップ内の値をブラウズし、ベクターにプッシュするだけで十分です:

vector<Type1> ConvertType1(map<KeyTypeM, ValueTypeM>& input) 
{ 
    vector<Type1> result; 
    for (auto& pair : input) // assumes C++11 
     result.push_back(ConvType1(pair.first, pair.second)); 
    return result; 
} 

ノート

for (map<KeyTypeM, ValueTypeM>::iterator it = m.begin(); it != m.end(); ++it) 
    result.push_back(ConvType1(it->first, it->second)); 

ONEマップと1種類のために仕事を行います:あなたはC++ 11コンパイラ、使用していない場合。

template <class OutType, class KeyType, class ValueType, class Converter> 
vector<OutType> Convert(map<KeyType, ValueType>& input, Converter conv) 
{ 
    vector<OutType> result; 
    for (auto& pair : input) 
     result.push_back(conv(pair.first, pair.second)); 
    return result; 
} 

をそして、このようにそれを使用します:今、私たちは、テンプレートを使用して変換関数を一般化することができます

auto v1 = Convert<Type1>(m1, &ConvertType1); 
auto v2 = Convert<Type2>(m2, &ConvertType2); 
... 

あなたはboost::mplを使用して変換するために、タイプのリストを作成することによって、さらに行くことができるが、それはであるべき別の質問。

EDIT:あなたが言及したようなタイプ

の変換を一般化、型を変換する一般的な方法はありません、我々はすべての変換関数を記述する必要があります。だから我々が行うことができる唯一のことは、このように暗黙の型変換演算子を実装することによって、それは、よりエレガントにされています。これは、私たちの変換機能を簡素化し

struct KeyTypeM 
{ 
    ... // normal members 
    operator KeyTypeS() const 
    { 
     // do the conversion here 
    } 
}; 

// suppose we have the same for ValueTypeM and ValueTypeS 

// We can now use a single convert function: 

template <class OutType, class KeyTypeM, class ValueType M> 
OutType ConvertToStruct(const KeyTypeM& key, const ValueTypeM& value) 
{ 
     OutType result; 
     result.Key = key;  // will call the implicit conversion 
     result.Value = value; 
     return result; 
} 

template <class OutType, class KeyType, class ValueType> 
void Convert(map<KeyType, ValueType>& input, OutType out[]) 
{ 
    // out must have been initialized to a proper size to hold all the elements. 
    unsigned cursor = 0; 
    for (map<KeyTypeM, ValueTypeM>::iterator it = m.begin(); it != m.end(); ++it, ++cursor) 
     out[cursor] = ConvertToStruct<OutType>(it->first, it->second); 
} 

EDITを(アカウントに配列を取るために更新) 2:私たちは、アレイ構造を一般化するstd::pairを使用することができます。

template <class OutType, class KeyTypeM, class ValueType M> 
OutType ConvertToStruct(const KeyTypeM& key, const ValueTypeM& value) 
{ 
     OutType result; 
     result.first = key;  // will call the implicit conversion 
     result.second = value; 
     return result; 
} 

template <class OutKey, class OutValue, class KeyType, class ValueType> 
void Convert(map<KeyType, ValueType>& input, std::pair<OutKey, OutValue> out[]) 
{ 
    // out must have been initialized to a proper size to hold all the elements. 
    unsigned cursor = 0; 
    for (map<KeyTypeM, ValueTypeM>::iterator it = m.begin(); it != m.end(); ++it, ++cursor) 
     out[cursor] = ConvertToStruct<OutType>(it->first, it->second); 
} 

// Use this way: 

std::pair<OutKey, OutValue> arr[m.size()]; 
Convert(m, arr); 
+0

HI、JNいい例のためにありがとう。 1.残念ながら、C++ 11コンパイラはまだありません。 2.配列を参照パラメータで入力することはできますか?もしそうなら、一般化することもできますか?コンテナレベルでのみ生成するか、要素タイプconvert、つまり "ConvType1"を一般化することは可能ですか? – pepero

+0

2)編集方法について説明します。 3)変換の一般的な規則はありますか? intsanceの場合、マップの型は常に整数であり、配列の型は常に文字列ですか?ルールがまったくない場合、簡単に一般化することはできません。 'operator <<'を定義してlexical_castを使うという選択肢がありますが、それはstringとの間ですべての型を変換する方法があることを意味します。 –

+0

これらのキータイプのほとんどはintの構造体であり、attrはint&boolの構造体です。それに続く厳しい規則はない。 – pepero

関連する問題