C++
Oggetti callable
Ricerca…
introduzione
Gli oggetti callable sono la raccolta di tutte le strutture C ++ che possono essere utilizzate come una funzione. In pratica, questo è tutto ciò che è possibile passare alla funzione STL di C ++ 17 invoke () o che può essere utilizzata nel costruttore di std :: function, questo include: Puntatori di funzione, Classi con operatore (), Classi con implicito conversioni, riferimenti a funzioni, puntatori a funzioni membro, puntatori a dati membro, lambda. Gli oggetti callable sono usati in molti algoritmi STL come predicato.
Osservazioni
Un discorso molto utile di Stephan T. Lavavej ( <functional>: What's New, And Proper Use ) ( Slides ) porta alla base di questa documentazione.
Puntatori di funzione
I puntatori di funzione sono il modo più semplice per passare le funzioni in giro, che può anche essere usato in C. (Per ulteriori dettagli, consultare la documentazione C ).
Ai fini degli oggetti chiamabili, un puntatore a funzione può essere definito come:
typedef returnType(*name)(arguments); // All
using name = returnType(*)(arguments); // <= C++11
using name = std::add_pointer<returnType(arguments)>::type; // <= C++11
using name = std::add_pointer_t<returnType(arguments)>; // <= C++14
Se dovessimo usare un puntatore a funzione per scrivere il nostro ordinamento vettoriale, sembrerebbe:
using LessThanFunctionPtr = std::add_pointer_t<bool(int, int)>;
void sortVectorInt(std::vector<int>&v, LessThanFunctionPtr lessThan) {
if (v.size() < 2)
return;
if (v.size() == 2) {
if (!lessThan(v.front(), v.back())) // Invoke the function pointer
std::swap(v.front(), v.back());
return;
}
std::sort(v, lessThan);
}
bool lessThanInt(int lhs, int rhs) { return lhs < rhs; }
sortVectorInt(vectorOfInt, lessThanInt); // Passes the pointer to a free function
struct GreaterThanInt {
static bool cmp(int lhs, int rhs) { return lhs > rhs; }
};
sortVectorInt(vectorOfInt, &GreaterThanInt::cmp); // Passes the pointer to a static member function
In alternativa, avremmo potuto richiamare il puntatore alla funzione in uno dei seguenti modi:
-
(*lessThan)(v.front(), v.back()) // All
-
std::invoke(lessThan, v.front(), v.back()) // <= C++17
Classi con operatore () (Funzionalità)
Ogni classe che sovraccarica l' operator()
può essere utilizzata come oggetto funzione. Queste classi possono essere scritte a mano (spesso denominate funtori) o generate automaticamente dal compilatore scrivendo Lambdas da C ++ 11 in poi.
struct Person {
std::string name;
unsigned int age;
};
// Functor which find a person by name
struct FindPersonByName {
FindPersonByName(const std::string &name) : _name(name) {}
// Overloaded method which will get called
bool operator()(const Person &person) const {
return person.name == _name;
}
private:
std::string _name;
};
std::vector<Person> v; // Assume this contains data
std::vector<Person>::iterator iFind =
std::find_if(v.begin(), v.end(), FindPersonByName("Foobar"));
// ...
Poiché i funtori hanno una propria identità, non possono essere inseriti in un typedef e questi devono essere accettati tramite argomenti del template. La definizione di std::find_if
può essere simile a:
template<typename Iterator, typename Predicate>
Iterator find_if(Iterator begin, Iterator end, Predicate &predicate) {
for (Iterator i = begin, i != end, ++i)
if (predicate(*i))
return i;
return end;
}
Da C ++ 17 in poi, la chiamata del predicato può essere eseguita con invoke: std::invoke(predicate, *i)
.