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;
}