/ / Passando una funzione membro della classe a for_each - class, c ++ 11, for-loop, foreach

Passare una funzione membro della classe a for_each - class, c ++ 11, for-loop, foreach

La mia domanda è: come faccio a passare una funzione membro della classe in for_each

Codice Sto cercando di mettermi al lavoro: (funziona quando la funzione è definita al di fuori della classe)

La parte che fallisce è commentata - quella che usa for_each con la funzione come funzione membro della classe

Qualche consiglio su come farlo funzionare?

#include <iostream>
#include <algorithm>
#include <vector>

void my_function(std::string str)
{
std::cout << "processing settings: " << str << std::endl;
}

class Settings_vector{

public:
std::vector <std::string> settings;

Settings_vector(){                          // push back vector of objects
settings.push_back("settings 1");
settings.push_back("settings 2");
settings.push_back("settings 3");
settings.push_back("settings 4");
}

void tester(std::string settings_string){
std::cout << "processing settings: " << settings_string << std::endl;
}
};

int main()
{
//std::vector<std::string> my_vector;

Settings_vector settings_vector;

std:: cout << "doing things the non-class wayn" << std::endl;
for_each(settings_vector.settings.begin(), settings_vector.settings.end(),     my_function); // testing function
// WORKS
/*
std:: cout << "doing things the modern wayn" << std::endl;
for_each(settings_vector.settings.begin(), settings_vector.settings.end(),    settings_vector.tester); // testing function
// FAILS
*/

std:: cout << "doing things the oldskool wayn" << std::endl;
for (int i = 0;i<settings_vector.settings.size();++i) {
settings_vector.tester(settings_vector.settings[i]);
}
// WORKS


return 0;
}

risposte:

6 per risposta № 1

Il modo più semplice sarebbe usare un'espressione lambda. Un approccio un po 'più complesso è quello di usare std::bind() associare tutti gli argomenti noti (qui l'istanza della classe alla funzione membro) e lasciare argomenti sconosciuti con i segnaposto _1, _2, eccetera.

#include <iostream>
#include <algorithm>
#include <vector>

class Settings_vector
{
Settings_vector()
: settings { "settings 1"
, "settings 2"
, "settings 3"
, "settings 4"
}
{}

void tester(std::string settings_string)
{ std::cout << "processing settings: " << settings_string << std::endl; }

public:
std::vector <std::string> settings;
};

int main()
{
Settings_vector settings_vector;

using namespace std;
using namespace std::placeholders;  // for _1

// Possibility Nr. 1: Use a Lambda Function
for_each( settings_vector.settings.begin(), settings_vector.settings.end()
, [&settings_vector](auto input){ settings_vector.tester(input); }
)
;

// Possibility Nr. 2: Partially bind existing arguments and use placeholders for others
for_each( settings_vector.settings.begin(), settings_vector.settings.end()
, std::bind(&Settings_vector::tester, &settings_vector, _1);
)
;

return 0;
}

spiegazioni:

  • Penso che un lambda sia diretto. Nelle parentesi quadre, dichiari ciò che entra in una chiusura. Qui passiamo settings_vector. Precedendolo con & significa che questa istanza viene passata per riferimento. In parentesi, dichiariamo i parametri per la funzione. Ho barato un po ', come auto nelle espressioni lambda è stato introdotto in C ++ 14, ma è possibile scriverlo come tipo std::string anche.

  • std::bind() lega i parametri a un puntatore di funzione e restituisce un oggetto callable. Se tutti i parametri sono presenti, il callable restituito non ha parametri e può essere chiamato come: callable(). Qui, vogliamo un callable per accettare il risultato dell'iterazione. Quindi, usiamo un segnaposto _1, che afferma che questo argomento verrà modificato al momento della chiamata. Ora rimangono 2 cose:

    • Ottenere un puntatore a una funzione membro. Questo è fatto usando &TypeName::MemberName, in questo caso &Settings_vector::tester.

    • Passando a this puntatore a una chiamata di funzione membro: &settings_vector. Quando si chiama una funzione membro, un oggetto deveessere passato per il quale viene chiamata questa funzione membro. Poiché abbiamo appena ottenuto un puntatore a una funzione membro senza alcun oggetto associato, è per questo che è il secondo parametro &settings_vector.