Error when using set_union and set_intersection - c++

I have two sets and I'm trying to do a union (I get the same error when doing an intersection). Here is the error:
error C3892: 'std::_Tree_const_iterator<_Mytree>::operator *' : you cannot assign to a variable that is const
Code snippet(if I comment out the line with the --> then the code compiles and my work around way of doing the union works fine):
set<Line *>::iterator it;
set<Line *> * newSet = new set<Line *>();
leftLines = pLeft->getSet();
rightLines = pRight->getSet();
-->it = set_union(leftLines->begin(),leftLines->end(),rightLines->begin(), rightLines->end(), newSet->begin());
for(it = leftLines->begin(); it != leftLines->end(); it++)
{
newSet->insert(*it);
}
for(it = rightLines->begin(); it != rightLines->end(); it++)
{
newSet->insert(*it);
}
it = newSet->begin();
while(it != newSet->end())
{
result->insert(*it);
it++;
}
I'm sure this is something silly but I'm kind of lost. I think that code snippet should be enough but I can provide whatever else is needed. Thanks.

This is C++, not Java [edit: or .NET]. You almost certainly want to replace (for example):
set<Line *> * newSet = new set<Line *>();
with just:
set<Line *> newSet;
...or, better still, probably just:
set<Line> newSet;
Although it's impossible to say for certain based on the code you've posted, there's a pretty fair chance that your left and right shouldn't be dealing in pointers either -- if they're going to do anything of the sort, a reference probably makes more sense (though, as I said, based on just what you've posted, it's impossible to say for sure).
Once you've done that, you run into a minor problem: a "normal" iterator over a set (or multiset, map or multimap) is really a const_iterator. Once you insert something into an associative container, you're not allowed to change it because that could destroy the collection's invariant (being sorted). If you want to change an existing item, you need to delete if from the contain, make the change, and insert the changed object back into the container. In your case, you're just inserting new items, so you want an insert_iterator.
Since you're not planning on modifying either left or right, you might as well treat them as const as well:
std::set_union(left.cbegin(), left.cend(),
right.cbegin(), right.cend(),
std::inserter(newSet, newSet.end()));
If you decide to simulate set_union on your own, you can do something like this:
std::set<Line> newSet(left.cbegin(), left.cend());
std::copy(right.cbegin(), right.cend(), std::inserter(newSet, newSet.end()));
Edit:
Instead of passing around pointers to containers, you normally want to pass around iterators into the containers. For example, to print out the contents, you apparently now have something like:
void print_data(std::vector<Line *> const *data) {
for (int i=0; i<data->size(); i++)
std::cout << *(*data)[i] << "\n";
}
It probably has more formatting and such, but for the moment we'll ignore those details and assume it's this simple. To write the data directly from a container of your choice, you normally want a template that will accept iterators of an arbitrary type:
template <class inIt>
void print_data(inIt begin, inIt end) {
while (begin != end)
std::cout << *begin++ << '\n';
}
We can, however, go a step further than that, and specify the output as an iterator as well:
template <class inIt, class outIt>
void print_data(inIt begin, inIt end, outIt dest) {
while (begin != end) {
*dest++ = *begin++;
*dest++ = '\n';
}
}
You could go one more step, and allow the user to specify the delimiter to be used between the items, instead of always using '\n', but at that point, you'd just be duplicating something what's already in the standard library -- a combination of std::copy and an std::ostream_iterator, which is how you probably want to deal with this in reality:
std::copy(newSet.begin(), newSet.end(),
std::ostream_iterator<Line>(std::cout, "\n"));
Note, however, that as far as the standard library cares, an ostream_iterator is just another iterator. If you're just going to print out the union of left and right, you can skip even creating a set to hold that union, and just print it out directly:
std::set_union(left.cbegin(), left.cend(),
right.cbegin(), right.cend(),
std::ostream_iterator<Line>(std::cout, "\n"));
The fact that an ostream_iterator writes to a file instead of putting things into a normal collection is entirely irrelevant to the standard library. It has a few classes of iterators, and can write output to any iterator that models the correct class.
Now, I may be jumping the gun, so to speak -- maybe need to do other processing on the data before you write it to the console. My point isn't that you necessarily have to write the union directly to standard output, but just that you don't necessarily have to write it to some other collection before you print it out.

set iterators aren't output iterators. Use this:
set_union(leftLines->begin(),leftLines->end(),rightLines->begin(), rightLines->end(), inserter(*newSet, newSet->begin()));
Also, why're you filling newSet? Leave it as is after the union/intersection or the union/intersection will be pointless.
set<Line *>::iterator it;
set<Line *> newSet; // No need to `new` this
leftLines = pLeft->getSet();
rightLines = pRight->getSet();
set_union(leftLines->begin(),leftLines->end(),rightLines->begin(), rightLines->end(), inserter(newSet, newSet.begin()));
// Assuming you really need the below code - you could likely just make an inserter directly on `result` instead of the copying.
it = newSet.begin();
while(it != newSet.end())
{
result->insert(*it);
it++;
}

Related

Filter and modify elements in boost::multi_index from an equal_range query

I have a boost::multi_index with a hashed_non_unique view. What I would like to accomplish is, given a key in that view, use
pair<myIter, myIter> iterRange = myView.equal_range(key);
for (myIter iter = iterRange.first; iter != iterRange.second; ++iter) {
// ...
}
to find all elements associated with that key. Then, run these elements through a filter
bool filter(Element e) { /* some filtering logic*/ }
and modify the filtered results with a modifier
void modifier(Element e) { /* modify the elements with e.g. myView.modify() */ }
However, simply putting these pieces together doesn't work since modifying the elements results in reordering of the multi_index, which renders my iterRange invalid.
What would be the correct way to do this? Thanks!
Some comments to your proposed solution:
BMIter is not special as you seem to imply, but merely the iterator associated to the first index of the container. Note that this will be the same as myIter when myView happens to be this first index.
Nevertheless, iterators of hashed indices are not invalidated by insertions or modifications, so you're safe. In fact, you could have defined iters as a vector<myIter> and store the iterators directly without any further conversion --you're still achieving the intended effect of not being affected by potential reorderings after modification.
Even though what you're doing is perfectly fine, if you're into squeezing some additional performance note that modification of elements in a hashed index does not change the underlying ordering when the key remains equivalent, so the only way a reordering can possibly affect you when traversing a range of equivalent keys is when a modified element jumps directly after the range (i.e, just before iterRange.second). With this mind, you can spare the iters trick as follows:
for (myIter iter = iterRange.first; iter != iterRange.second; ) {
auto nextIter = std::next(iter);
if (filter(*iter)) {
myView.modify(iter, modifier);
if (nextIter != iterRange.second && std::next(iter) == iterRange.second)
iterRange.second = iter;
}
iter = nextIter;
}
I think I've found the answer myself. Instead of simply modifying the elements inside the for loop, we need to cache the elements first and modify them later to avoid altering the ordering. The trick here is, instead of caching the iterators to this specific view, cache instead iterators to the elements themselves, i.e.
vector<BMIIter> iters;
for (myIter iter = iterRange.first; iter != iterRange.second; ++iter) {
if (filter(*iter)) {
iters.push_back(myBMI.iterator_to(*iter));
}
}
for (auto iter : iters) {
myBMI.modify(iter, modifier);
}
Note that BMIIter and myIter are different iterator types - the former is an iterator to the element itself, while the latter is iterator specific to myView. Modifying elements in the multi_index invalidates the latter, but the former still holds valid even after reordering happened.

Iterating over std::set<unique_ptr>, how to keep track which ones to remove?

I need to loop over some objects of class T.
They are stored in an std::set<std::unique_ptr<T>> tees.
The main purpose of the loop's body is to use the objects, but by doing that I will also find out when some of the objects are no longer needed and can be deleted.
I am using a range-based for loop for iterating over the unique_ptrs:
for (std::unique_ptr<T> & tee : tees)
I know I cannot call tees.erase(tee) inside the loop (UB). Therefore I should collect the unique_ptrs that need to be deleted in a helper collection. Problem: The pointers are unique, therefore I cannot copy them into the helper collection.
I could collect the raw pointers in a std::set<T*>, but how would I use these after the loop to delete the matching unique_ptrs from the tees collection? Also, collecting the raw pointers again somehow feels wrong when I made the effort to use smart pointers in this problem.
I could switch to shared_ptr, but the pointers would only ever be shared for the purpose of deleting the objects. Does not feel right.
I could switch from range-based for to something else, like handling the iterators myself, and get the next iterator before deleting the entry. But going back to pre-C++11 techniques also does not feel right.
I could switch to std::remove_if. (EDIT: I can't, actually. Explained in comments below this question and below the accepted answer.) The loop's body would move into the unary_predicate lambda. But the main purpose of the loop is not to determine whether the objects should be deleted, but to make use of them, altering them.
The way of least resistance seems to be to go back to iterator-handling, that way I do not even need a helper collection. But I wonder if you can help me with a C++11-ish (or 14,17) solution?
I don't think you are going to find anything easier than
for(auto it = container.begin(), it != container.end();)
{
//use *it here
if(needs_to_be_erased)
it = container.erase(it);
else
++it;
}
since std::set does not provide mutable access to its elements any sort of transform or remove will not work. You would have to build a container of iterators and then after you process the set go through that container of iterators calling erase for each one.
I think you can copy the positions into a new data structure and remove these items in another loop by accessing the new data structure in reverse order.
int counter =0;
vector<int> indices;
for (unique_ptr<T> & tee : tees)
{
if (bCondition)
indices.push_back(counter);
counter++;
}
reverse(indices.begin(), indices.end());
for (int i : indices)
tees.erase(tees.begin() + i);
Not exactly a solution but if you have to do this a lot you could make your own algorithm for it. I guess the reason this is not in the standard library is because the algorithm needs to know the container to perform an erase.
So you could do something like this:
template<typename Cont, typename Pred>
void erase_if(Cont& c, decltype(std::begin(c)) b, decltype(std::end(c)) e, Pred p)
{
while(b != e)
{
if(p(*b))
b = c.erase(b);
else
++b;
}
}
template<typename Cont, typename Pred>
void erase_if(Cont& c, Pred p)
{ erase_if(c, std::begin(c), std::end(c), p); }
Then call it something like:
erase_if(tees, [](std::unique_ptr<int> const& up){
// use up here...
return (*up) & 1; // erase if odd number
});
or
erase_if(tees, std::begin(tees), std::end(tees), [](std::unique_ptr<int> const& up){
// use up here...
return (*up) & 1; // erase if odd number
});

loop through several vectors

I had trouble searching for potential duplicates because I'm not sure what the correct terminology is.
If I have many vectors which are already created, how can I loop through them? To make things simple, suppose I have three vectors of strings named "vec_one", "vec_two", "vec_three".
I want to do something like:
for i in ("vec_one", "vec_two", "vec_three") {
for (vector<string>::const_iterator iter = i.begin(); iter != i.end(); ++iter) {
//do something with the elements ***and I need to access "i"***, that is, the vector name.
}
}
This would be the same as writing three different for loops, but would be more readable and in fact I have more than three in my non-simple application.
Note that because I need to access the vector name (see the comment), I can't just merge them all together and then run one loop.
You can do it with an array:
const vector<string>* varr[] = { &vec_one, &vec_two, &vec_three, &etc };
for (auto vec = begin(varr); vec < end(varr); ++vec)
for (vector<string>::const_iterator iter = begin(**vec); iter != end(**vec); ++iter)
//do something with the elements
You could put the the vectors in a vector<std::pair<std::string, std::vector<...>*>:
std::vector<std::pair<std::string, std::vector<std::string>*> > vectors;
vectors.emplace_back(std::string("vec_one"), &vec_one); //or push_back(std::make_pair(...)) in C++03
vectors.emplace_back(std::string("vec_two"), &vec_two);
vectors.emplace_back(std::string("vec_three"), &vec_three);
for(auto iter = vectors.begin(); iter != vectors.end(); ++iter)//used c++11 auto here for brevity, but that isn't necessary if C++11 is not availible
for(auto vecIter = iter->second->begin(); vecIter != iter->second->end(); ++vecIter)
//get name with iter->first, body here
That way you can get the name easily from the outer iterator.
If you use C++11 you can use std::array instead:
std::array<std::pair<std::string, std::vector<std::string>*>, 3> vectors =
{
std::make_pair(std::string("vec_one"), &vec_one),
std::make_pair(std::string("vec_two"), &vec_two),
std::make_pair(std::string("vec_three"), &vec_three)
};
In C++03 you could use buildin arrays instead, but unless the extra overhead for the vector is a problem for you (unlikely) I don't see a compelling reason to do so. boost::array is also a noteworthy alternative if you can't use C++11
If you do need the absolute optimal performance it might be worthwile to directly use const char* instead of std::string for the names.
Probably the easiest way would be to have your vectors in an array (or a vector-of-vectors if there is a variable number of them).
I guess you'd also want an array of "vector names" to satisfy your second condition.

Shorter way to get an iterator for a std::vector

Lets say that I have got a vector like this.
std::vector<a_complicated_whatever_identifier *> *something
= new std::vector<a_complicated_whatever_identifier *>;
// by the way, is this the right way to do this?
Now I want to get an iterator for this... so I would do this like this.
std::vector<a_complicated_whatever_identifier *>::iterator iter;
But I find it a little too much for my code. I wonder, is there any more, brief way to ask for an iterator regardless of the type?
I was thinking in something like.
something::iterator iter;
// OK, don’t laugh at me, I am still beginning with C++
Well, it obviously fail, but I guess you get the idea. How to accomplish this or something similar?
You would typically give your containers sensible typedefs, and then it's a breeze:
typedef std::pair<int, Employee> EmployeeTag;
typedef std::map<Foo, EmployeeTag> SignInRecords;
for (SignInRecords::const_iterator it = clock_ins.begin(); ... )
^^^^^^^^^^^^^^^^^
Usually, having a handy typedef for the container is more practical and self-documenting that an explicit typedef for the iterator (imagine if you're changing the container).
With the new C++ (11), you can say auto it = clock_ins.cbegin() to get a const-iterator.
Use a typedef.
typedef std::vector<complicated *>::iterator complicated_iter
Then set them like this:
complicated_iter begin, end;
In C++11 you'll be able to use auto.
auto iter = my_container.begin();
In the meantime just use a typedef for the vector:
typedef std::vector<a_complicated_whatever_identifier *> my_vector;
my_vector::iterator iter = my_container.begin();
You should rarely have much need/use for defining an iterator directly. In particular, iterating through a collection should normally be done by a generic algorithm. If there's one already defined that can do the job, it's best to use it. If there's not, it's best to write your own algorithm as an algorithm. In this case, the iterator type becomes a template parameter with whatever name you prefer (usually something referring at least loosely to the iterator category):
template <class InputIterator>
void my_algorithm(InputIterator start, InputIterator stop) {
for (InputIterator p = start; p != stop; ++p)
do_something_with(*p);
}
Since they've been mentioned, I'll point out that IMO, typedef and C++11's new auto are (at least IMO) rarely a good answer to this situation. Yes, they can eliminate (or at least reduce) the verbosity in defining an object of the iterator type -- but in this case, it's basically just treating the symptom, not the disease.
As an aside, I'd also note that:
A vector of pointers is usually a mistake.
Dynamically allocating a vector is even more likely a mistake.
At least right off, it looks rather as if you're probably accustomed to something like Java, where you always have to use new to create an object. In C++, this is relatively unusual -- most of the time, you want to just define a local object so creation and destruction will be handled automatically.
// by the way, is this the right way to do this?
What you are doing is correct. The best approach depends on how you want to use that vector.
But I find it a little too much for my code. I wonder, is there any
more, brief way to ask for an iterator regardless of the type?
Yes, you can define the vector as a type:
typedef std::vector<a_complicated_whatever_identifier *> MyVector;
MyVector * vectPtr = new MyVector;
MyVector::iterator iter;
If you have a recent compiler, I suggest giving c++11 a spin. Most compilers support it in the form of the --std=c++0x flag. You can do all kinds of nifty things related to type inference:
std::list<std::map<std::string, some_complex_type> > tables;
for (auto& table: tables)
{
std::cout << table.size() << std::endl;
}
for (auto it = tables.begin(); it!= tables.end(); ++it)
{
std::cout << it->size() << std::endl;
}
Also look at decltype and many other handyness:
// full copy is easy
auto clone = tables;
// but you wanted same type, no data?
decltype(tables) empty;
Contrived example of combining typedefs with the above:
typedef decltype(tables) stables_t;
typedef stables_t::value_type::const_iterator ci_t;

what is the better way to write iterators for a loop in C++

For a very simple thing, like for example to print each element in a vector, what is the better way to use in C++?
I have been using this:
for (vector<int>::iterator i = values.begin(); i != values.end(); ++i)
before, but in one of the Boost::filesystem examples I have seen this way:
for (vec::const_iterator it(v.begin()), it_end(v.end()); it != it_end; ++it)
For me it looks more complicated and I don't understand why is it better then the one I have been using.
Can you tell me why is this version better? Or it doesn't matter for simple things like printing elements of a vector?
Does i != values.end() make the iterating slower?
Or is it const_iterator vs iterator? Is const_iterator faster in a loop like this?
Foo x = y; and Foo x(y); are equivalent, so use whichever you prefer.
Hoisting the end out of the loop may or may not be something the compiler would do anyway, in any event, it makes it explicit that the container end isn't changing.
Use const-iterators if you aren't going to modify the elements, because that's what they mean.
for (MyVec::const_iterator it = v.begin(), end = v.end(); it != end; ++it)
{
/* ... */
}
In C++0x, use auto+cbegin():
for (auto it = v.cbegin(), end = v.cend(); it != end; ++it)
(Perhaps you'd like to use a ready-made container pretty-printer?)
for (vector<int>::iterator i = values.begin(); i != values.end(); ++i)
...vs...
for (vec::const_iterator it(v.begin()), it_end(v.end()); it != it_end; ++it)
For me [the latter, seen in boost] looks more complicated and I don't understand why is it better then the one I have been using.
I'd say it would look more complicated to anybody who hasn't got some specific reason for liking the latter to the extent that it distorts perception. But let's move on to why it might be better....
Can you tell me why is this version better? Or it doesn't matter for simple things like printing elements of a vector?
Does i != values.end() make the iterating slower?
it_end
Performance: it_end gets the end() value just once as the start of the loop. For any container where calculating end() was vaguely expensive, calling it only once may save CPU time. For any halfway decent real-world C++ Standard library, all the end() functions perform no calculations and can be inlined for equivalent performance. In practice, unless there's some chance you may need to drop in a non-Standard container that's got a more expensive end() function, there's no benefit to explicitly "caching" end() in optimised code.This is interesting, as it means for vector that size() may require a small calculation - conceptually subtracting begin() from end() then dividing by sizeof(value_type) (compilers scale by size implicitly during pointer arithmetic), e.g. GCC 4.5.2:
size_type size() const
{ return size_type(this->_M_impl._M_finish - this->_M_impl._M_start); }
Maintenance: if the code evolves to insert or erase elements inside the loop (obvious in such a way that the iterator itself isn't invalidated - plausible for maps / sets / lists etc.) it's one more point of maintenance (and hence error-proneness) if the cached end() value also needs to be explicitly recalculated.
A small detail, but here vec must be a typedef, and IMHO it's often best to use typedefs for containers as it loosens the coupling of container type with access to the iterator types.
type identifier(expr)
Style and documentary emphasis: type identifier(expr) is more directly indicative of a constructor call than type identifier = expr, which is the main reason some people prefer the form. I generally prefer the latter, as I like to emphasise the sense of assignment... it's visually unambiguous whereas function call notation is used for many things.
Near equivalence: For most classes, both invoke the same constructor anyway, but if type has an explicit constructor from the type of expr, it will be passed over if = is used. Worse still, some other conversion may allow a less ideal constructor be used instead. For example, X x = 3.14;, would pass over explicit X::X(double); to match X::X(int) - you could get a less precise (or just plain wrong) result - but I'm yet to be bitten by such an issue so it's pretty theoretical!
Or is it const_iterator vs iterator? Is const_iterator faster in a loop like this?
For Standard containers, const_iterator and iterator perform identically, but the latter implies you want the ability to modify the elements as you iterate. Using const_iterator documents that you don't intend to do that, and the compiler will catch any contradictory uses of the iterator that attempt modification. For example, you won't be able to accidentally increment the value the iterator addresses when you intend to increment the iterator itself.
Given C++0x has been mentioned in other answers - but only the incremental benefit of auto and cbegin/cend - there's also a new notation supported:
for (const Foo& foo: container)
// use foo...
To print the items in a vector, you shouldn't be using any of the above (at least IMO).
I'd recommend something like this:
std::copy(values.begin(), values.end(),
std::ostream_iterator<T>(std::cout, "\n"));
You could just access them by index
int main(int argc, char* argv[])
{
std::vector<int> test;
test.push_back(10);
test.push_back(11);
test.push_back(12);
for(int i = 0; i < test.size(); i++)
printf("%d\n", test[i]);
}
prints out:
10
11
12
I don't think it matters. Internally, they do the same thing, so you compiler should optimise it anyway. I would personally use the first version as I find it much clearer as it closely follows the for-loop strucutre.
for (vector<int>::iterator i = values.begin(); i != values.end(); ++i)