在C ++中,我使用transform将地图的所有值更改为大写。
std::map<std::string, std::string> data = getData();
// make all values uppercase
std::transform(data.begin(), data.end(), data.begin(),
[](std::pair<std::string, std::string>& p) {
boost::to_upper(p.second);
return(p);
});
这给了我以下编译错误:
/opt/local/include/gcc46/c++/bits/stl_algo.h:4805:2: error: no match for call to '(main(int, char**)::<lambda(std::pair<std::basic_string<char>, std::basic_string<char> >&)>) (std::pair<const std::basic_string<char>, std::basic_string<char> >&)
我认为我的lambda表达式中的参数类型有问题。这可能很简单,但我似乎无法弄清楚预期的是什么。
答案 0 :(得分:22)
你缺少第一种类型的const。
[](std::pair<const std::string, std::string>& p) {
但这不是您的问题:您不能使用map
作为OutputIterator,因为它们不支持赋值。但是,您可以使用std::for_each
改变第二个参数。
好老map_to_foobar
:
std::for_each(data.begin(), data.end(),
[](std::pair<const std::string, std::string>& p) {
p.second = "foobar";
});
概念性的东西:调用transform
与输入和输出的范围相同是非常合理的,如果所有的仿函数都按值返回并且不改变它们的参数,那么这很有意义。但是,对某些内容进行变更可能会更快(或者至少在代码中看起来更快,更不用说优化编译器)并且对成员函数有很大意义。
答案 1 :(得分:2)
如果您打算坚持使用std::transform
,则需要std::inserter()
:
C ++ 03 MVCE
typedef std::map<int, std::string> Map;
struct ToUpper
{
Map::value_type & operator()(Map::value_type & pair) const
{
boost::to_upper(pair.second);
return pair;
}
};
int main()
{
Map m;
m[0] = "snake_case";
m[1] = "camelCase";
m[2] = "PascalCase";
std::transform(m.begin(), m.end(), std::inserter(m, m.end()), ToUpper());
for (Map::const_iterator it = m.begin(); it != m.end(); ++it)
std::cout << it->first << ", " << it->second << std::endl;
}
C ++ 11 (您实际上可以在main()
中进行所有操作)
int main()
{
auto m = getData();
auto toUpper = [] (decltype(m)::value_type & pair)
{
boost::to_upper(pair.second);
return pair;
};
std::transform(m.begin(), m.end(), std::inserter(m, m.end()), toUpper);
for (auto const & pair : m)
std::cout << pair.first << ", " << pair.second << std::endl;
}
C ++ 14 (您可以在lambda参数中使用auto
)
int main()
{
auto m = getData();
auto toUpper = [] (auto & pair)
{
boost::to_upper(pair.second);
return pair;
};
std::transform(m.begin(), m.end(), std::inserter(m, m.end()), toUpper);
for (auto const & pair : m)
std::cout << pair.first << ", " << pair.second << std::endl;
}
C ++ 17 (仅因为我喜欢结构化绑定)
int main()
{
auto m = getData();
auto toUpper = [] (auto & pair)
{
boost::to_upper(pair.second);
return pair;
};
std::transform(m.begin(), m.end(), std::inserter(m, m.end()), toUpper);
for (auto const & [key, value] : m)
std::cout << key << ", " << value << std::endl;
}