the template guide geeksforgeeks example c++ templates

template - Deducción de plantilla C++ de lambda



template function c++ (4)

¿Realmente necesitas std::function allí? std::function es útil cuando necesita borrado de tipo . Con las plantillas, usualmente puedes omitirlo por completo:

template<class F1, class F2> void examplFunction(F1 func, F2 func2, decltype(func2(func()))* sfinae = nullptr) { auto x = func(); func2(x); }

El parámetro sfinae se asegura de que solo se pueda llamar a la función con funciones tales que se pueda llamar a func2 con el resultado de func .

Tengo una función que toma dos std::function s como argumentos. El parámetro de la segunda función tiene el mismo tipo que el resultado de la primera.

Escribí una plantilla de función como esta:

template<typename ResultType> void examplFunction(std::function<ResultType()> func, std::function<void(ResultType)> func2) { auto x = func(); func2(x); }

Puedo llamarlo con:

void f() { examplFunction<int>([]() { return 1; }, // [](int v) { std::cout << "result is " << v << std::endl; }); }

¿Hay alguna manera de deshacerse de <int> en examplFunction<int> y dejar que el compilador deduzca el tipo de ResultType ?


La respuesta de Angew es excelente (y debería ser la respuesta aceptada), pero falta el detalle menor de la verificación de que la función de sección no devuelve nada. Para hacerlo, deberá utilizar el rasgo de tipo std :: is_void y std :: enable_if:

template<class F1, class F2> void examplFunction(F1 func, F2 func2, std::enable_if_t<std::is_void_v<decltype(func2(func()))>, void*> sfinae = nullptr) { auto x = func(); func2(x); }

Este obvio es más detallado y difícil de leer si no está familiarizado con los rasgos de tipo y SFINAE, por lo que probablemente no sea la mejor manera de avanzar si no necesita asegurarse de que F2 se devuelva.


Sí hay.

template<typename ResultType> void examplFunction_impl(std::function<ResultType()> func, std::function<void(ResultType)> func2) { auto x = func(); func2(x); } template<class F1, class F2> void examplFunction(F1&& f1, F2&& f2) { using ResultType = decltype(f1()); examplFunction_impl<ResultType>(std::forward<F1>(f1), std::forward<F2>(f2)); }

Demo

En este caso, necesita que f1 sea ​​invocable sin argumentos, para que pueda averiguar el tipo de retorno en la función auxiliar. Luego llama a la función real mientras especifica explícitamente ese tipo de retorno.

Podría agregar algo de SFINAE para asegurarse de que esta función solo participe en la resolución de sobrecarga cuando f1 pueda invocarse así (y si f2 también puede invocarse con el valor de retorno de f1 ).

Aunque tengo que estar de acuerdo con @Angew en que en el ejemplo dado no hay necesidad de la std::function . Eso podría ser, por supuesto, diferente en una situación del mundo real.


std::function tiene un constructor con plantilla (y por lo demás sin restricciones), por lo que deducirlo simplemente de un tipo de argumento no es tan fácil de tratar. Si esos argumentos aún necesitan ser std::function s, puede omitir una <int> al precio de dos std::function s, y dejar que las guías de deducción hagan el resto:

void f() { examplFunction(std::function([]() { return 1; }), // std::function([](int v) { std::cout << "result is " << v << std::endl; })); }

Un dato divertido es que esto no siempre funciona. Por ejemplo, la implementación actual de libc ++ carece de guías para la std::function , violando así el estándar.