Estoy tratando de proporcionar una función que llame a una lambda proporcionada, y me pregunto si es posible hacer que devuelva un valor predeterminado si la función tiene el tipo de retorno void
.¿Hay alguna manera de coincidir en el valor de retorno en C++ 11?
Esto es lo que tengo hasta ahora, una función que devuelve el valor de retorno de la lambda, pero si el lambda es void
, devuelve 20.
#include <functional>
#include <iostream>
template <typename H>
auto f(H&& h) -> decltype(h(), void())
{
return h();
}
template <typename H>
auto f(H&& h) -> decltype(h(), int())
{
h();
return 20;
}
int main()
{
int r = f([](){ std::cout << "test1" << std::endl; return 10; }); // error here
std::cout << "r: " << r << std::endl;
r = f([](){ std::cout << "test2" << std::endl; });
std::cout << "r: " << r << std::endl;
return 0;
}
Esto produce el error,
test.cpp:20:68: error: call of overloaded ‘f(main()::<lambda()>)’ is ambiguous
Por lo tanto, esto se debe simplemente a que C++ no puede usar el polimorfismo en función del tipo de devolución. Sin embargo, me pregunto si hay algunos buenos trucos de C++ 11, como un mejor uso de decltype
o alguna magia de plantilla, que podría hacer esto posible. Lo estoy preguntando porque, por lo que puedo ver, no hay ninguna ambigüedad real aquí ... el compilador está infiriendo el tipo de retorno void
y diciendo que es ambiguo si coincide con la versión int
o void
de f
, lo cual es un poco tonto.
Una razón para hacer esto es que si la función f
espera un valor de retorno, pero el usuario proporciona una lambda que no incluya una declaración return
, el compilador infiere un tipo void
, y los errores hacia fuera. Dado que en el escenario real tengo una buena idea de lo que debería ser un valor de retorno predeterminado razonable cuando el usuario no se preocupa de proporcionar uno, me pregunto si es posible hacer que el compilador permita a los usuarios descuidar la declaración return
que a menudo es innecesaria por conveniencia.
Gracias. Debo mencionar que estoy usando GCC 4.6.3.
respuesta: en base a sugerencia de utilizar enable_if
de Xeo, se me ocurrió lo siguiente, que parece funcionar:
template <typename H>
auto f(H&& h) -> typename std::enable_if<std::is_same<decltype(h()), void>::value, int>::type
{
h();
return 20;
}
template <typename H>
auto f(H&& h) -> typename std::enable_if<std::is_same<decltype(h()), int>::value, int>::type
{
return h();
}
Gracias!
has probado f en las funciones normales? – CharlesB
Sí, en las funciones normales también es ambiguo. – Steve
Segundo parámetro de 'decltype': ¿Puedo preguntar para qué sirve? (Realmente, porque no lo sé!). – 0x499602D2