Potenzia il problema della libreria phoenix o lambda: rimozione di elementi da uno std :: vector

StackOverflow https://stackoverflow.com/questions/213953

  •  03-07-2019
  •  | 
  •  

Domanda

Di recente ho riscontrato un problema che pensavo che boost :: lambda o boost :: phoenix potesse aiutare a risolvere, ma non ero in grado di ottenere la sintassi giusta e quindi l'ho fatto in un altro modo. Quello che volevo fare era rimuovere tutti gli elementi in & Quot; stringhe & Quot; che erano meno di una certa lunghezza e non in un altro contenitore.

Questo è il mio primo tentativo:

std::vector<std::string> strings = getstrings();
std::set<std::string> others = getothers();
strings.erase(std::remove_if(strings.begin(), strings.end(), (_1.length() < 24 &&  others.find(_1) == others.end())), strings.end());

Come ho finito per farlo è stato questo:

struct Discard
{
    bool operator()(std::set<std::string> &cont, const std::string &s)
    {
        return cont.find(s) == cont.end() && s.length() < 24;
    }
};

lines.erase(std::remove_if( lines.begin(), lines.end(), boost::bind<bool>(Discard(), old_samples, _1)), lines.end());
È stato utile?

Soluzione

È necessario boost :: labmda :: bind per chiamate di funzione lambda-ify, ad esempio la lunghezza < 24 parte diventa:

bind(&string::length, _1) < 24

Modifica

Vedi il post di " Head Geek " per perché set :: find è complicato. L'ha ottenuto per risolvere il set corretto :: find overload (quindi ho copiato quella parte), ma ha perso un boost essenziale :: ref () - motivo per cui il confronto con end () ha sempre fallito (il contenitore è stato copiato) .

int main()
{
  vector<string> strings = getstrings();
  set<string> others = getothers();
  set<string>::const_iterator (set<string>::*findFn)(const std::string&) const = &set<string>::find;
  strings.erase(
    remove_if(strings.begin(), strings.end(),
        bind(&string::length, _1) < 24 &&
        bind(findFn, boost::ref(others), _1) == others.end()
      ), strings.end());
  copy(strings.begin(), strings.end(), ostream_iterator<string>(cout, ", "));
  return 0;
}

Altri suggerimenti

Il problema principale, oltre alle bind chiamate (Adam Mitz era corretto in quella parte), è che std::set<std::string>::find è una funzione sovraccarica, quindi non è possibile specificarlo direttamente nella find chiamata. Devi dire al compilatore quale others.end() usare, in questo modo:

using namespace boost::lambda;
typedef std::vector<std::string> T1;
typedef std::set<std::string> T2;

T1 strings = getstrings();
T2 others = getothers();

T2::const_iterator (T2::*findFn)(const std::string&) const=&T2::find;
T2::const_iterator othersEnd=others.end();

strings.erase(std::remove_if(strings.begin(), strings.end(),
    (bind(&std::string::length, _1) < 24
        && bind(findFn, boost::ref(others), _1) == othersEnd)),
    strings.end());

Questo viene compilato, ma non funziona correttamente, per motivi che non ho ancora capito ... la funzione <=> non restituisce mai <=>, quindi non elimina mai nulla. Continuo a lavorare su quella parte.

EDIT: correzione, la <=> funzione sta restituendo <=>, ma il confronto non lo riconosce. Non so perché.

MODIFICA DOPO: Grazie al commento di Adam, vedo cosa non va e ho risolto il problema. Ora funziona come previsto.

(Guarda la cronologia delle modifiche se vuoi vedere il mio programma di test completo.)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top