2016-12-20 1 views
1

In meinem Projekt ein VektorC++ benutzerdefiniertes Objekt aus dem Vektor entfernen: std :: remove_if ': keine passende überladene Funktion gefunden

std::vector<std::shared_ptr<MovingEntity>>gameObjects; 

Was ich will, ist Elemente löschen, wenn sie die Kriterien erfüllen.

Methode Elemente zu löschen:

void GameWorld::catchBees() 
{ 
    auto q = std::remove_if(bees.begin(), bees.end(), beeToClose); 
    bees.erase(q); 
} 

Methode beeToClose:

bool GameWorld::beeToClose(const MovingEntity & bee) 
{ 
    std::shared_ptr<Beekeeper> keeper = std::static_pointer_cast<Beekeeper>(m_beekeeper); 
    if (bee.getConstPosition().distanceTo(m_beekeeper->getPosition()) > keeper->getCatchDistance()) 
    { 
     return true; 
    } 

    return false; 
} 

Wenn ich versuche, den Code zu kompilieren bekomme ich einige Fehler, die ich versucht zu verstehen:

' GameWorld :: beeToClose ': Nicht-Standard-Syntax; Verwendung '&' einen Zeiger

Nicht sicher zu erstellen, warum diese Nachricht

'std :: remove_if' gegeben: keine passende überladene Funktion

finde ich nicht erklären BeeToClose richtig?

'q': kann nicht verwendet werden, bevor es SDLFramework initialisiert

q, weil nicht initialisiert:

std::remove_if(bees.begin(), bees.end(), beeToClose); 

nicht richtig läuft?

Wie kann ich ein std :: shared_ptr korrekt aus einem Vektor korrekt entfernen, wenn einige Kriterien erfüllt sind?

Antwort

5

Die Syntax zum Bilden eines Zeigers für die Elementfunktion lautet &ClassName::FunctionName. Sie benötigen also &GameWorld::beeToClose für einen Zeiger auf die Elementfunktion beeToClose. In Ihrem Fall sollten Sie eine Lambda verwenden, von dem Sie diese Funktion auch

auto q = std::remove_if(bees.begin(), bees.end(), 
        [&](shared_ptr<MovingEntity> const& bee){ return beeToClose(bee); }); 

nennen, sind Sie in die falsche vector::erase Überlastung verwenden, können Sie das eine, die eine Reihe von Elementen löscht, nicht derjenige, der ein löscht einzelnes Element.

bees.erase(q, bees.end()); 
+0

wirklich entfernen, wenn nur 'Verwenden Sie [&]'. – Yakk

+0

@Yakk Gut, haben Sie Ihren Weg :) Ich verlinkte die Lambda-Dokumentation, so dass das OP seine Lieblings-Capture auswählen kann. – Praetorian

2

Die vectorstd::shared_ptr<MovingEntity> enthalten Elemente, so braucht ein beeToClose()const std::shared_ptr<MovingEntity> & Parameter als Eingabe zu akzeptieren, nicht ein const MovingEntity & Parameter. Außerdem scheint beeToClose() eine nicht statische Klassenmethode zu sein, die auf ein nicht statisches Klassenmitglied zugreift (m_beekeeper), so dass Sie beeToClose() nicht direkt an std::remove_if() übergeben können, da es keinen Zugriff auf das this Zeigerobjekt des Aufrufobjekts hat kann es in ein Lambda wickeln, um den Zeiger this zu erfassen.

Try this:

void GameWorld::catchBees() 
{ 
    auto q = std::remove_if(bees.begin(), bees.end(), 
     [this](const const std::shared_ptr<MovingEntity> &bee) { 
      return this->beeToClose(bee); 
     } 
    ); 
    bees.erase(q, bees.end()); 
} 

bool GameWorld::beeToClose(const std::shared_ptr<MovingEntity> &bee) 
{ 
    std::shared_ptr<Beekeeper> keeper = std::static_pointer_cast<Beekeeper>(m_beekeeper); 
    return (bee->getConstPosition().distanceTo(m_beekeeper->getPosition()) > keeper->getCatchDistance()); 
} 

Sie könnten auch erwägen die Entfernungsberechnung in Beekeeper stattdessen bewegt:

bool GameWorld::beeToClose(const std::shared_ptr<MovingEntity> &bee) 
{ 
    std::shared_ptr<Beekeeper> keeper = std::static_pointer_cast<Beekeeper>(m_beekeeper); 
    return !keeper->isInCatchDistance(bee); 
} 

bool Beekeeper::isInCatchDistance(const std::shared_ptr<MovingEntity> &bee) 
{ 
    return (bee->getConstPosition().distanceTo(getPosition()) <= getCatchDistance()); 
} 
Verwandte Themen