C++
Callable objekt
Sök…
Introduktion
Callable objekt är samlingen av alla C ++ strukturer som kan användas som en funktion. I praktiken är detta allt du kan skicka till C ++ 17 STL-funktionen åberopa () eller som kan användas i konstruktören av std :: -funktionen, detta inkluderar: Funktionspekare, klasser med operatör (), klasser med implicit konverteringar, Hänvisningar till funktioner, Pekare till medlemsfunktioner, Pekare till medlemsdata, lambdas. De kallbara objekten används i många STL-algoritmer som predikat.
Anmärkningar
Ett mycket användbart föredrag av Stephan T. Lavavej ( <funktionell>: Nyheter och korrekt användning ) ( Slides ) leder till basen i denna dokumentation.
Funktionspekare
Funktionspekare är det mest grundläggande sättet att överföra funktioner som också kan användas i C. (Se C-dokumentationen för mer information).
I syfte att räkna ut objekt kan en funktionspekare definieras som:
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
Om vi skulle använda en funktionspekare för att skriva vår egen vektorsort, skulle det se ut som:
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
Alternativt kunde vi ha åberopat funktionspekaren på något av följande sätt:
-
(*lessThan)(v.front(), v.back()) // All
-
std::invoke(lessThan, v.front(), v.back()) // <= C++17
Lektioner med operatör () (Functors)
Varje klass som överbelaster operator()
kan användas som ett funktionsobjekt. Dessa klasser kan skrivas för hand (ofta kallad funktorer) eller automatiskt genereras av kompilatorn genom att skriva Lambdas från C ++ 11 på.
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"));
// ...
Eftersom funktorer har sin egen identitet kan de inte läggas in i en typedef och dessa måste accepteras via mallargument. Definitionen av std::find_if
kan se ut:
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;
}
Från C ++ 17 kan predikatets anrop göras med invoke: std::invoke(predicate, *i)
.