¿Cómo sobrecargar una función lambda local simple?
SSE del problema original:
#include <iostream>
#include <map>
void read()
{
static std::string line;
std::getline(std::cin, line);
auto translate = [](int idx)
{
constexpr static int table[8]{ 7,6,5,4,3,2,1,0 };
return table[idx];
};
auto translate = [](char c)
{
std::map<char, int> table{ {'a', 0}, {'b', 1}, {'c', 2}, {'d', 3},
{'e', 4}, {'f', 5}, {'g', 6}, {'h', 7} };
return table[c];
};
int r = translate(static_cast<int>(line[0]));
int c = translate(static_cast<char>(line[1]));
std::cout << r << c << std::endl;
}
int main()
{
read();
return 0;
}
Los mensajes de error
error: conflicting declaration 'auto translate'
note: previous declaration as 'read()::<lambda(int)> translate'
Por favor, no le importe no verificar la entrada del usuario, este es un SSE.
c++
lambda
overloading
c++17
function-object
snoopy
fuente
fuente
translate
son solo variables locales que no pueden reutilizar el mismo nombre.Respuestas:
¡No, no puedes sobrecargar la lambda!
Las lambdas son functores anónimos (es decir, objetos de función sin nombre) y no funciones simples. Por lo tanto, sobrecargar esos objetos no es posible. Lo que básicamente intentas hacer es casi
Lo cual no es posible, ya que el mismo nombre de variable no se puede reutilizar en C ++.
Sin embargo, en c ++ 17 tenemos
if constexpr
por qué uno puede instanciar la única rama que es verdadera en tiempo de compilación.Lo que significa que las posibles soluciones son:
decltype
para laif constexpr
verificación. (Créditos @NathanOliver )Usando la plantilla variabe puedes hacer algo como. ( Vea una demostración en vivo en línea )
y llámalo como
Usando lambda genérico (desde c ++ 14 ), lo anterior será: ( Vea una demostración en vivo en línea )
y llama a la lambda como lo haces ahora:
fuente
else if
necesitas serelse if constexpr
. En segundo lugar, ¿por qué usar una plantilla variable? Podrías hacer que el lambda sea genérico y tus checls se convertiríanif constexpr (std::is_same_v<decltype(idx), int>)
yelse if constexpr (std::is_same_v<decltype(idx), char>)
Las lambdas son básicamente azúcar sintáctico para functores definidos localmente. Hasta donde yo sé, nunca fueron destinados a ser sobrecargados para ser llamados con diferentes parámetros. Tenga en cuenta que cada expresión lambda es de un tipo diferente, por lo que incluso el error inmediato a un lado, su código no puede funcionar según lo previsto.
Sin embargo, puede definir un functor con una sobrecarga
operator()
. Esto sería exactamente lo que obtendría de lambdas si fuera posible. Simplemente no obtienes la sintaxis concisa.Algo como:
fuente
Por lo tanto, las reglas para sobrecargar los nombres solo se aplican a ciertos tipos de búsqueda de nombres de funciones (tanto gratuitos como métodos).
Las lambdas no son funciones, son objetos con un operador de llamada a función. Por lo tanto, la sobrecarga no puede ocurrir entre dos lambdas diferentes.
Ahora, puede obtener una resolución de sobrecarga para trabajar con objetos de función, pero solo dentro del alcance de un solo objeto. Y luego, si hay más de uno
operator()
, la resolución de sobrecarga puede elegir entre ellos.Sin embargo, una lambda no tiene una forma obvia de tener más de una
operator()
. Podemos escribir una clase de utilidad simple (en c ++ 17 ) para ayudarnos:y una guía de deducciones:
Con estos dos, podemos sobrecargar dos lambdas:
y hecho.
La escritura
overloaded
es posible tanto en c ++ 14 como en c ++ 11, pero requiere más trabajo y es menos elegante. Una vez que esté consciente del problema, encontrar una solución que coincida con lo que su compilador particular admite en cuanto a las características de C ++ no debería ser difícil.fuente
variadic generic lamda
+if constexpr
para separar las llamadas?