C++ STL:使用transform将map的键复制到异构map并填充默认值
问题
需要将const map<string, string>类型的容器:
const map<string, string> digits = {{"zero", "0"},{"one", "1"},{"two", "2"},{"three", "3"},{"four", "4"},{"five", "5"},{"six", "6"},{"seven", "7"},{"eight", "8"},{"nine", "9"}};
转换为map<string, uint>类型的容器:
map<string, uint> out = {{"zero", 0},{"one", 0},{"two", 0},{"three", 0},{"four", 0},{"five", 0},{"six", 0},{"seven", 0},{"eight", 0},{"nine", 0}};
希望通过简洁的STL算法实现,已尝试以下代码:
map<string, uint> counting; transform(begin(digits), end(digits), inserter(counting, end(counting)), [](auto & p) { return {p.first, 0}; });
疑问:是否可以对异构迭代器使用transform算法?
解答
你的代码本身完全可行,std::transform天然支持异构迭代器场景——也就是输入迭代器和输出迭代器指向的元素类型不同的情况。
为什么你的代码能正常工作?
- 输入迭代器遍历的是
const map<string, string>的元素,类型是pair<const string, string>; - 你的lambda把每个输入元素转换成
pair<string, uint>(编译器会自动适配成map<string, uint>要求的pair<const string, uint>类型); std::inserter生成的插入迭代器,会调用目标map的insert方法插入转换后的键值对,这完全符合transform的要求:只要输出迭代器能处理转换后的元素类型即可。
可选的更清晰写法
如果想让代码可读性更强,可以做小调整,核心逻辑和你原代码一致:
map<string, uint> counting; std::transform(digits.cbegin(), digits.cend(), std::inserter(counting, counting.end()), [](const auto& p) { return std::make_pair(p.first, 0U); });
这里用cbegin()/cend()明确是常量迭代器,make_pair让类型推导更直观,但你原代码的列表初始化写法完全没问题。
关于异构迭代器的说明
std::transform的设计初衷就是处理“输入元素转换后输出”的场景,根本不要求输入和输出的元素类型相同。只要输出迭代器能够接受转换后的元素(比如赋值、插入操作合法),异构迭代器的使用就完全没有问题。
内容的提问来源于stack exchange,提问作者alexlyee
相关产品推荐
相关产品推荐

