使用 std::transform 将 std::vector<struct{key; val;}> 转换为 std::map<key, val>

Using std::transform to convert a std::vector<struct{key; val;}> into a std::map<key, val>

鉴于这些类型:

struct ComplexLibraryThing { /*lots of fields*/};
typedef std::map<int, ComplexLibraryThing> MyMap;
struct ShadowComplexLibraryThing { /*Shadow of ComplexLibraryThing*/};
struct MyVecType { int a; ShadowComplexLibraryThing b; };
typedef std::vector<MyVecType> MyVector;

我可以这样做进行序列化(我的序列化库不支持类地图类型):

MyVecType map2pair(std::pair<int, ComplexLibraryThing> const &myPair)
{
    MyVecType retVal;
    retVal.a = myPair.first;
    retVal.b = convertForSerialisation(myPair.second);
    return retVal;
}

MyMap myMap = {...};
MyVector myVector;
std::transform(myMap.begin(),
               myMap.end(),
               std::back_inserter(myVector),
               map2pair);

然后我将矢量发送到想要重建 MyMap 的接收方。但是,我找不到合适的 <algorithm> 模板来进行反序列化,如下所示:

MyMap myNewMap;
for (auto const &entry: myVector)
    myNewMap[entry.a] = convertForDeserialisation(entry.b);

我如何使用 <algorithm> 来写这个?

(请注意,地图中的 ComplexLibraryThing 类型不能轻易更改,但我也有一个 ShadowComplexLibraryThing 可以)

此 post 展示了如何为 std::map 创建插入器:

How to insert into std::map?‌ p

迭代对象的类型需要是 std::pair<KeyType, EntryType>(所谓的 std::mapvalue_type)。

我觉得是这样的:

std::pair<int, ComplexLibraryThing> vec2pair(const MyVecType &myVec)
{
    return std::make_pair(myVec.a,
                          transformForDeserialization(myVec.b));
}

MyVector myVector = {...};
MyMap myMap;
std::transform(myVector.begin(),
               myVector.end(),
               std::inserter(myMap, myMap.end()),
               vec2pair);

我认为 "trick" 缺少的关键是 std::inserter。这是一个小演示。

#include <algorithm>
#include <iterator>
#include <map>
#include <vector>

struct foo {int a; int b;};

std::vector<foo> GenerateSource() {
  return {};
} 

std::pair<int, int> ConvertFooToMapPair(const foo& f) {
    return {f.a, f.b};
}

int main(int argc, char* argv[]) {
  std::map<int, int> destination;
  std::vector<foo> source = GenerateSource();
  std::transform(
    source.begin(), source.end(),
    std::inserter(destination, destination.end()),
    ConvertFooToMapPair);
}