Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 4343988
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 21, 20262026-05-21T11:49:55+00:00 2026-05-21T11:49:55+00:00

I couldn’t find an instance of how to do this, so I was hoping

  • 0

I couldn’t find an instance of how to do this, so I was hoping someone could help me out. I have a map defined in a class as follows:

std::map<std::string, TranslationFinished> translationEvents;

TranslationFinished is a boost::function. I have a method as part of my class that iterates through this map, calling each of the functions like so:

void BaseSprite::DispatchTranslationEvents()
{
    for(auto it = translationEvents.begin(); it != translationEvents.end(); ++it)
    {
        it->second(this);
    }
}

However it’s possible for a function called by it->second(this); to remove an element from the translationEvents map (usually itself) using the following function:

bool BaseSprite::RemoveTranslationEvent(const std::string &index)
{
    bool removed = false;
    auto it = translationEvents.find(index);
    if (it != translationEvents.end())
    {
        translationEvents.erase(it);
        removed = true;
    }
    return removed;
}

doing this causes a debug assertion fail when the DispatchTranslationEvents() tries to increment the iterator. Is there a way to iterate through a map safely with the possibility that a function call during the iteration may remove an element from the map?

Thanks in advance

EDIT: Accidently C/Pd the wrong Remove Event code. Fixed now.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-21T11:49:56+00:00Added an answer on May 21, 2026 at 11:49 am

    After reading all other answers, I am at an advantage here… But here it goes.

    However it’s possible for a function called by it->second(this); to remove an element from the translationEvents map (usually itself)

    If this is true, that is, a callback can remove any element from the container, you cannot possibly resolve this issue from the loop itself.

    Deleting the current callback

    In the simpler case where the callback can only remove itself, you can use different approaches:

    // [1] Let the callback actually remove itself
    for ( iterator it = next = m.begin(); it != m.end(); it = next ) {
       ++next;
       it->second(this);
    }
    // [2] Have the callback tell us whether we should remove it
    for ( iterator it = m.begin(); it != m.end(); ) {
       if ( !it->second(this) ) {                   // false means "remove me"
          m.erase( it++ );
       } else {
          ++it;
       }
    }
    

    Among these two options, I would clearly prefer [2], as you are decoupling the callback from the implementation of the handler. That is, the callback in [2] knows nothing at all about the container in which it is held. [1] has a higher coupling (the callback knows about the container) and is harder to reason about as the container is changed from multiple places in code. Some time later you might even look back at the code, think that it is a weird loop (not remembering that the callback removes itself) and refactor it into something more sensible as for ( auto it = m.begin(), end = m.end(); it != end; ++it ) it->second(this);

    Deleting other callbacks

    For the more complex problem of can remove any other callback, it all depends on the compromises that you can make. In the simple case, where it only removes other callbacks after the complete iteration, you can provide a separate member function that will keep the elements to remove, and then remove them all at once after the loop completes:

    void removeElement( std::string const & name ) {
       to_remove.push_back(name);
    }
    ...
    for ( iterator it = m.begin(); it != m.end(); ++it ) {
       it->second( this );       // callback will possibly add the element to remove
    }
    // actually remove
    for ( auto it = to_remove.begin(); it != to_begin.end(); ++it ) {
       m.erase( *it );
    }
    

    If removal of the elements need to be immediate (i.e. they should not be called even in this iteration if they have not yet been called), then you can modify that approach by checking whether it was marked for deletion before executing the call. The mark can be done in two ways, the generic of which would be changing the value type in the container to be a pair<bool,T>, where the bool indicates whether it is alive or not. If, as in this case, the contained object can be changed you could just do that:

    void removeElement( std::string const & name ) {
       auto it = m.find( name );           // add error checking...
       it->second = TranslationFinished(); // empty functor
    }
    ...
    for ( auto it = m.begin(); it != m.end(); ++it ) {
       if ( !it->second.empty() )
          it->second(this);
    }
    for ( auto it = m.begin(); it != m.end(); ) { // [3]
       if ( it->second.empty() )
          m.erase( it++ );
       else
          ++it;
    }
    

    Note that since a callback can remove any element in the container, you cannot erase as you go, as the current callback could remove an already visited iterator. Then again, you might not care about leaving the empty functors for a while, so it might be ok just to ignore it and perform the erase as you go. Elements already visited that are marked for removal will be cleared in the next pass.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Couldn't find an answer to this unfortunately so hoping someone can help. In Spring
I couldn't find anything similar to this anywhere. I have an array of pointers
I couldn't find this in the documentation. If I have a complex object in
Couldn't find anything relevant in forums So ,Please help me with this code .I'm
Couldn't find an answer to this one. I have a WPF ListView control that
couldn't find my solution. hope you can help. I want to have a url
Couldn't find anything about this topic. I have a Windows TCP C++ server application
I couldn't find any reference to this question. I have an array of structs
I couldn't find anything on this, but probably its just because I don't know
I couldn't find a suitable title for this. I'm going to express my query

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.