How to apply transform to an STL map in C++
You are missing the const in the first type of the pair.
[](std::pair<const std::string, std::string>& p) {
However this is not your problem: You cannot use a map
as the OutputIterator, as they do not support assignment. You can, however mutate the second argument using std::for_each
.
Good old map_to_foobar
:
std::for_each(data.begin(), data.end(),
[](std::pair<const std::string, std::string>& p) {
p.second = "foobar";
});
Conceptual stuff: Calling transform
with the same range as input and output is quite legit and makes a lot of sense if all your functors return by value and don't mutate their arguments. However, mutating something in place can be a faster (or at least look faster in code, nevermind the optimizing compiler) and makes a lot of sense with member functions.
If you plan on sticking to std::transform
, then you need std::inserter()
:
C++03 MCVE
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 (you can do everything in main()
really)
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 (you can use auto
in lambda parameters)
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 (just because i love structured bindings)
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;
}