2

I have a multiset and I'm getting a range from it. I want to add this range in a vector to use it later, this is what I'm doing:

class foo
{
    public:
        int a;
        foo(int a) : a(a){}
};
class FooPointerCompare
{
    public:
        bool operator()(const foo* a, const foo* b)
        {
            return a->a < b->a;
        }
};

std::multiset<foo*, FooPointerCompare> m;
std::vector<std::multiset<foo*, FooPointerCompare>::iterator> v;
auto pair = m.equal_range(new foo(5)); //leak here, I know
v.insert(v.end(), pair.first, pair.second);

but I get these errors:

No matching constructor for initialization of 'std::__1::__tree_const_iterator<foo *, const std::__1::__tree_node<foo *, void *> *, int>'

No viable overloaded '='

when I use a simple for(auto it = pair.first; it != pair.second; it++) v.push_back(it); it works perfectly. What is wrong with my vector::insert call?

2
  • Btw, it's easier to write foo f(5); auto pair = m.equal_range(&f); than to write //leak here, I know ;-p Commented Nov 21, 2012 at 18:24
  • @SteveJessop true enough :P, in the real code I was using a smart pointer, but the reference to the local object sounds like a better alternative. Commented Nov 21, 2012 at 18:38

2 Answers 2

3

What's wrong is that

v.insert(v.end(), pair.first, pair.second);

is equivalent to

for (auto it = pair.first; it != pair.second; ++ it)
    v.push_back(*it);
//              ^

which is not the same as your intention. I don't think there's any standard algorithms to do what you want. It's better you just write out the for loop.

Sign up to request clarification or add additional context in comments.

1 Comment

Ah, that makes perfect sense! Thanks for the help.
3

vector::insert expects iterators that point to the values to be inserted into the vector.

Since you have a vector of iterators, you would have to pass it something that iterates over the iterators. But you're passing it something that iterates over the elements in your multiset.

So, this fails for the same reason that you can't do:

std::vector<char*> v;
char foo[10];
v.insert(v.end(), foo, foo+10);

or:

std::vector<int> v;
v.insert(v.end(), 0, 10);

One solution to all three problems is boost::counting_iterator. In your case:

v.insert(v.end(),
    boost::make_counting_iterator(pair.first), 
    boost::make_counting_iterator(pair.second)
);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.