Función que acepta funciones como parámetro con tipos de plantilla

Dec 18 2020

Soy bastante nuevo en programación y C ++. Tengo una función que quiero aceptar punteros de función con valores de plantilla como argumento. Esto es lo que quiero decir ...

tengo esta función:

template<typename... ColumnTypes, typename... ParameterTypes>
   void query(std::function<void(bool success, ozo::rows_of<ColumnTypes...>& results)> callback, const 
   std::string& query, ParameterTypes&& ... parameters);

"ozo :: rows_of" es un alias para:

template <typename ... Ts>
   std::vector<std::tuple<Ts...>> 

Quiero que a cada consulta se le proporcione una devolución de llamada, esta devolución de llamada deberá poder aceptar diferentes tipos. p.ej. "ColumnTypes"

Lo que he probado:

void myfunc(bool succeeded, ozo::rows_of<int>& results)
{
     //code
}

postgres_caller->query(myfunc, "SELECT length FROM this_table WHERE id > $1 AND id < $2;", 11, 14);

resultado:

.cpp:241:26: error: no matching member function for call to 'query'
    postgres_caller->query(myfunc, "SELECT length FROM this_table WHERE id > $1 AND id < $2;", 11, 14);
    ~~~~~~~~~~~~~~~~~^~~~~

.h: 165: 22: nota: plantilla candidata ignorada: no pudo coincidir 'función <void (bool, vector <tupla <tipo-parámetro-0-0 ...>, asignador <tupla <tipo-parámetro-0-0 ...>>> &)> 'contra' void (*) (bool, std :: vectorstd :: tuple <int, std :: allocatorstd :: tuple <int>> &) 'void PostgresCaller :: query (std :: function <void (bool success, ozo :: rows_of <ColumnTypes ...> & results)> callback, const std :: string & query, ParameterTypes && ... parámetros)

También probé con lambda:

postgres_caller->query([](bool succeeded, ozo::rows_of<int>& results)
                            {
                                //code
                            }, "SELECT length FROM this_table WHERE id > $1 AND id < $2;", 11, 14);

resultado:

error: no matching member function for call to 'query'
    postgres_caller->query([](bool succeeded, ozo::rows_of<int>& results)
    ~~~~~~~~~~~~~~~~~^~~~~

.h: 165: 22: nota: plantilla candidata ignorada: no pudo coincidir 'función <void (bool, vector <tupla <tipo-parámetro-0-0 ...>, asignador <tupla <tipo-parámetro-0-0 ...>>> &)> 'contra' (lambda en .cpp: 241: 32) 'void PostgresCaller :: query (std :: function <void (bool success, ozo :: rows_of <ColumnTypes ...> & resultados)> devolución de llamada, const std :: string & query, ParameterTypes && ... parámetros) ^

¿Es esto factible y cómo se puede hacer? muy apreciado. /John

Respuestas

1 super Dec 18 2020 at 23:02

La deducción de plantilla solo funciona en el tipo exacto que pasa, por lo que si pasa un puntero de función, la plantilla no puede deducir a qué tipo std::functionconvertir ese puntero de función.

Haga que el invocable sea un parámetro de plantilla, en lugar de usar std::function.

template<typename Callable, typename... ParameterTypes>
void query(Callable callback, const std::string& query, ParameterTypes&& ... parameters) {
    callback( ... ); // use it like this
}

La mayoría de las veces no es necesario deducir la firma de la devolución de llamada. Simplemente llámelo con los argumentos que espera que tome.

Si esto no es suficiente, también hay formas de deducir la firma de la devolución de llamada, pero se vuelve un poco más detallada y la mayoría de las veces no tiene un propósito real.