Função que aceita funções como parâmetro com tipos modelados

Dec 18 2020

Sou bastante novo em programação e C ++. Eu tenho uma função que quero aceitar ponteiros de função com valores modelados como argumento. Aqui está o que quero dizer ...

eu tenho esta função:

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" é o apelido de:

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

Quero que cada consulta receba um retorno de chamada, esse retorno de chamada precisará ser capaz de aceitar tipos diferentes. por exemplo. "ColumnTypes"

O que eu tentei:

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: observação: modelo candidato ignorado: não foi possível corresponder 'função <void (bool, vetor <tupla <parâmetro-tipo-0-0 ...>, alocador <tupla <parâmetro-tipo-0-0 ...>>> &)> 'contra' void (*) (bool, std :: vectorstd :: tuple <int, std :: allocatorstd :: tuple <int>> &) 'void PostgresCaller :: query (std :: função <void (sucesso de bool, ozo :: rows_of <ColumnTypes ...> & resultados)> callback, const std :: string & query, ParameterTypes && ... parâmetros)

Eu também tentei com 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: observação: modelo candidato ignorado: não foi possível corresponder 'função <void (bool, vetor <tupla <parâmetro-tipo-0-0 ...>, alocador <tupla <parâmetro-tipo-0-0 ...>>> &)> 'contra' (lambda em .cpp: 241: 32) 'void PostgresCaller :: query (std :: function <void (bool success, ozo :: rows_of <ColumnTypes ...> & resultados)> retorno de chamada, const std :: string & query, ParameterTypes && ... parameters) ^

Isso é viável e como pode ser feito? muito apreciado. /João

Respostas

1 super Dec 18 2020 at 23:02

A dedução de modelo funciona apenas no tipo exato que você passa, então se você passar um ponteiro de função, o modelo não pode deduzir para qual tipo std::functionconverter esse ponteiro de função.

Torne o chamável um parâmetro de modelo, em vez de usar std::function.

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

Na maioria das vezes, você não precisa deduzir a assinatura do retorno de chamada. Basta chamá-lo com os argumentos que você espera que ele aceite.

Se isso não for suficiente, também existem maneiras de deduzir a assinatura do retorno de chamada, mas fica um pouco mais prolixo e na maioria das vezes não tem nenhum propósito real.