C++
Objetos callables
Buscar..
Introducción
Los objetos recuperables son la colección de todas las estructuras de C ++ que se pueden usar como una función. En la práctica, esto es todo lo que puede pasar a la función C ++ 17 STL invoke () o que se puede usar en el constructor de la función std ::, que incluye: punteros de función, clases con operador (), clases con implícito conversiones, referencias a funciones, punteros a funciones miembros, punteros a datos de miembros, lambdas. Los objetos que se pueden llamar se utilizan en muchos algoritmos STL como predicado.
Observaciones
Una charla muy útil de Stephan T. Lavavej ( <functional>: Novedades y uso apropiado ) ( Diapositivas ) nos lleva a la base de esta documentación.
Punteros a funciones
Los punteros de función son la forma más básica de pasar funciones, que también se pueden utilizar en C. (Consulte la documentación de C para obtener más detalles).
A los efectos de los objetos que se pueden llamar, un puntero de función se puede definir como:
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
Si usaríamos un puntero de función para escribir nuestro propio ordenamiento vectorial, se vería así:
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
Alternativamente, podríamos haber invocado el puntero de función de una de las siguientes maneras:
-
(*lessThan)(v.front(), v.back()) // All
-
std::invoke(lessThan, v.front(), v.back()) // <= C++17
Clases con operador () (Functors)
Cada clase que sobrecargue al operator()
puede usarse como un objeto de función. Estas clases pueden ser escritas a mano (a menudo conocidas como funtores) o generadas automáticamente por el compilador escribiendo Lambdas desde C ++ 11 en.
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"));
// ...
Como los funtores tienen su propia identidad, no se pueden colocar en un typedef y estos deben aceptarse mediante el argumento de la plantilla. La definición de std::find_if
puede verse como:
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;
}
A partir de C ++ 17, la llamada del predicado se puede hacer con invocar: std::invoke(predicate, *i)
.