简体   繁体   中英

Why do I get the error 'vector iterators incompatible'?

I am writing a small UI for my program. I have the method onMouseMotion() , which I can call in one of two ways (see code); if I call it through std::function , then != operator in the for loop stop condition produces the run-time exception vector iterators incompatible . Why?

class Widget : public EventHandler
{
protected:
    /* ... */
    std::vector<Widget *> children_;                        
    std::function<bool(Event &)> func_;

private:
    bool onMouseMotion(Event &event);
    /* ... */   
};

Widget::Widget() 
{
    /* ... */
    func_ = std::bind(&Widget::onMouseMotion, this, std::placeholders::_1);
    /* ... */
}

bool Widget::processEvent(Event &event)
{
    if (event.getType() == ui::EventType::MouseMotionEvent) {

        /* Method 1 - onMouseMotion works ok */     
        onMouseMotion(event);

        /* Method 2 - onMouseMotion throws */
        //func_(event);

        return true;
    }
}

bool Widget::onMouseMotion(Event &event)
{
    /* exception occurs on the next line, only when using Method 2 above */
    for (auto child = children_.rbegin(); child != children_.rend(); ++child) {}
}

Updates :

  • program is single-threaded.
  • the exception is thrown when entering the for loop, zero iterations occur.
  • compiling with MSVC.
  • same exception with an empty for loop.
  • rewritten examples to illustrate the std::function problem.

So it is clear that

  • auto defines an iterator type for child, determined statically by the compiler (it cannot change between calls).
  • the type of child is assignment compatible with rbegin() and rend()
  • the type of child is relational operator compatible with rbegin() when called directly, but not when called through the bind() wrapper
  • since the type of child cannot change, the type of rend() must have, in the second case.

I see the following possibilities.

  1. The vector is a member and therefore the iterator type will be a pointer to member, and pointer to member has some restrictions on how it may be used.
  2. The value of this in the first case might be different from that captured in the bind (base class vs derived class, for example)
  3. The value of this may be delivered via a wrapper, which changes its type behaviour.

On balance, this is most likely to be an MSVC bug. The code as supplied does not compile and I am reluctant to try to modify and likely not be able to reproduce the bug. If you can post a repro case that compiles, I'd be happy to investigate further and update the answer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM