lebman
lebman

Reputation: 71

std::transform on a multiset giving me error C3892

I am trying to understand how the std::transform function works, but I'm having a bit of trouble with the following code. I want to take a multiset ms, add 1 to the contents of each element and store them in a new multiset msc. Here is what I have:

int op_increase(int i) { return ++i; }

int main()
{

std::multiset<int> ms = {1,1,2,2,3};
std::multiset<int> msc;
std::transform(ms.begin(), ms.end(), msc.begin(), op_increase);

return 0;
}

However I get the following error:

C3892: _Dest: you cannot assign to a variable that is const

Upvotes: 2

Views: 498

Answers (2)

PaulMcKenzie
PaulMcKenzie

Reputation: 35440

Your code was not utilizing the correct argument to std::transform that allows insertion into an empty container. This requires using an iterator that is intelligent enough to call the appropriate function that calls the container's insert() function.

The solution is to provide std::transform the std::inserter iterator that automatically inserts into the empty multiset. Here is an example:

#include <set>
#include <algorithm>
#include <iterator>

int op_increase(int i) { return ++i; }

int main()
{
    std::multiset<int> ms = {1,1,2,2,3};
    std::multiset<int> msc;
    std::transform(ms.begin(), ms.end(), std::inserter(msc, msc.begin()), op_increase);
    // msc now contains 2,2,3,3,4  
}

Note the std::inserter is used, and not merely msc.begin(). The inserter will automatically insert the items into the map.

Live Example

Upvotes: 4

alexeykuzmin0
alexeykuzmin0

Reputation: 6440

The problem here is that std::multiset<T>::begin() returns a std::_Tree_const_iterator type. That's why you cannot change its value. This behavior is sensible: the std::multiset, like std::set, is a sorted container typicaly implemented as a red-black tree, and thus change of a value of one element may require update of the whole data structure. If user really wants to do this, he may erase a node and add it back.

To better understand the std::transform behavior, you may use std::vector container instead of std::multiset. Cplusplus.com contains a good example of code using std::transform.

Also, as far as I understand from your code, you try to add the resulting data into the initially empty std::multiset. To achieve this functionality, you may use std::insert_iterator (Cplusplus.com), like this:

int op_increase(int i) { return ++i; }

int main()
{
    std::multiset<int> ms = {1,1,2,2,3};
    std::multiset<int> msc;
    std::transform(ms.begin(), ms.end(), inserter(msc, msc.begin()), op_increase);
    return 0;
}

Upvotes: 2

Related Questions