I'd like to create a set of a range of numbers: 0, 1, 2, 3, 4, ... The following code fails to compile:
std::set<int> s;
std::iota(s.begin(), s.end(), 0);
with the following error message:
error C3892: '_First' : you cannot assign to a variable that is const
The compiler is VC++2012. The same code works fine for a vector. How should I use it with a set?
UPDATE
I can see now that my code is meaningless, because there's no set size specified.
Here are some more details about my problem.
I have a set containing SOME numbers from [0, N] range. In my application I need to calculate set difference many times for such sets. N is fixed.
Let's say N = 5
and the first set is s1 = {0, 3, 4}
. I need to calculate set difference {0, 1, 2, 3, 4} \ {0, 3, 4} == {1, 2}
. This operation should be performed quite often for different sets, so I thought that I could create a set with all numbers ({0, 1, 2, 3, 4}
in this case) and use std::set_difference
to calculate those differences.
To solve your actual problem: std::set_difference
has less to do with std::set
than you might expect. You can use any pair of iterators as the first two parameters of set_difference
provided they return the values in order. There is no particular benefit in it being a set.
So for example the begin/end iterators of a std::vector
containing the values 0 ... n-1 in order would work, or a pair of boost::counting_iterator
:
std::set result;
std::set_difference(
boost::counting_iterator<int>(0), boost::counting_iterator<int>(n),
s1.begin(), s1.end(),
std::inserter(result, result.end())
);
The output doesn't need to be a set either, you could just as well use a vector
with back_inserter
.
To solve what you asked: it doesn't make sense to try to use iota
on a set. iota
changes the values contained in a range, by assigning new values to them. You can't assign to the values in a set
.
If you want a set containing the numbers 0 ... n-1
, then:
std::set<int> s;
for (int i = 0; i < n; ++i) {
s.insert(s.end(), i);
}
If someone told you that loops are for wusses and real C++ programmers use algorithms, then you can get iota
involved if you really want:
std::set<int> s;
{
std::vector<int> vec(n);
std::iota(vec.begin(), vec.end(), 0);
s.insert(vec.begin(), vec.end());
}
Unfortunately that's kind of inefficient. So if you love algorithms so much that you might as well marry them, then you can reach outside the standard libraries:
std::set<int> s(boost::counting_iterator<int>(0), boost::counting_iterator<int>(n));
A slightly inelegant alternative:
set<int> s;
generate_n(inserter(s, s.end()), 10, [&]{ return s.size(); });
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With