在c ++中复制类似数据结构的任何模板方式,通用方法?

时间:2012-03-02 09:35:15

标签: c++ templates stl

我有一系列类似的结构,例如,

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

我需要编写一个函数,比如重载赋值运算符,将data_series中的数据转换为另一个函数,反之亦然。

因此,不是按地图映射键按键 int by int ,而不是按照模板方式进行操作这样做,所以代码是通用的,或保存更多的代码行?什么是明智的方法呢?

编辑1:

不幸的是,由于我们的遗留系统导致了一个约束,即struct之间的类型转换,例如key1,key_1不能用作C ++原语,因此还必须提供转换功能。

编辑2:

受到J.N.的启发回答,有可能有类似的东西:

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

如何为key和attr转换generlize?喜欢

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

1 个答案:

答案 0 :(得分:3)

好的,我们假设有这个:

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

note :如果您没有C ++ 11编译器,请使用:

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

这将完成一个地图和一种类型的工作。现在我们可以使用模板来概括转换函数:

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创建要转换的类型列表,但这应该是另一个问题。

编辑:概括了类型的转换

正如您所提到的,没有通用的方法来转换类型,我们必须编写所有的转换函数。所以我们唯一能做的就是通过实现这样的隐式转换运算符来使它更优雅:

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);
}

编辑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);