¿Qué son los functores en C++ y para qué sirven?
\n\nImagine que está escribiendo código en C++ y necesita pasar un comportamiento (una función) a otra función, por ejemplo, para ordenar o filtrar datos. La solución clásica son los punteros a funciones. Pero tienen desventajas: no almacenan estado, son difíciles de integrar (inline) y se ven un poco arcaicos. Aquí entran en escena los functores en C++ (también conocidos como objetos-función o objetos funcionales C++).
\n\nUn functor es una clase o estructura común en la que se sobrecarga el operador de llamada a función operator(). Gracias a esto, una instancia de dicha clase se puede usar como una función normal. ¿Suena complicado? En realidad es una de las herramientas más elegantes de C++. En Stack Overflow, la pregunta "What are C++ functors and their uses?" ha acumulado miles de visitas — los desarrolladores quieren entender este tema para escribir código más flexible y eficiente. En esta guía lo desglosaremos todo: desde la sintaxis básica hasta ejemplos reales de uso con STL.
Sintaxis básica: cómo crear tu primer functor
\n\nCrear un functor se reduce a tres pasos:
\n- \n
- Declarar una clase o estructura. \n
- Implementar dentro
operator()con la firma deseada (parámetros y tipo de retorno). \n - Crear un objeto de esta clase y llamarlo como una función. \n
Aquí hay un ejemplo de functor C++ muy simple que multiplica un número por dos:
\n\n#include <iostream>\n\nclass Multiplier {\npublic:\n // Sobrecargamos el operador ()\n int operator()(int x) const {\n return x * 2;\n }\n};\n\nint main() {\n Multiplier mult; // Creamos el objeto-función\n std::cout << mult(5) << std::endl; // Salida: 10\n std::cout << mult(10) << std::endl; // Salida: 20\n return 0;\n}\n\nObserve: mult(5) parece una llamada a función normal, pero en realidad es una llamada a mult.operator()(5). El compilador aplica azúcar sintáctico y el código se vuelve limpio e intuitivo.
Ventaja principal: los functores pueden almacenar estado
\n\nA diferencia de las funciones normales o las expresiones lambda (antes de C++11), los objetos función C++ pueden tener sus propios campos miembro. Esto abre enormes posibilidades. Por ejemplo, puede crear un functor que no solo ejecute una acción, sino que también recuerde cuántas veces ha sido llamado:
\n\n#include <iostream>\n\nclass Counter {\nprivate:\n int count = 0;\npublic:\n int operator()() {\n return ++count;\n }\n int getCount() const { return count; }\n};\n\nint main() {\n Counter counter;\n std::cout << counter() << std::endl; // 1\n std::cout << counter() << std::endl; // 2\n std::cout << counter() << std::endl; // 3\n // ¡El estado se conserva entre llamadas!\n return 0;\n}\n\nEste ejemplo de functor C++ con estado no se puede implementar con una función simple sin usar variables globales (lo cual es malo). Los functores resuelven este problema de manera elegante y segura.
\n\nFunctores y algoritmos STL: la combinación perfecta
\n\nLa aplicación más poderosa de los functores es trabajar con algoritmos de la Standard Template Library (STL). Algoritmos como std::sort, std::find_if, std::for_each esperan recibir un objeto invocable (callable). Puede pasarles un functor, y este ejecutará la lógica deseada.
Ejemplo: ordenamiento con functor
\n\nSupongamos que tiene un vector de números y desea ordenarlos de forma descendente. Puede escribir su propio functor de comparación:
\n\n#include <iostream>\n#include <vector>\n#include <algorithm>\n\nclass Descending {\npublic:\n bool operator()(int a, int b) const {\n return a > b; // Dev