Хорошо, давайте предположим, что у нас есть это:
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);