Функция, принимающая функции как параметр с шаблонными типами

Dec 18 2020

Я новичок в программировании и C ++. У меня есть функция, которую я хочу принимать указатели на функции с шаблонными значениями в качестве аргумента. Вот что я имею в виду ...

у меня есть эта функция:

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" - это псевдоним для:

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

Я хочу, чтобы каждый запрос был снабжен обратным вызовом, этот обратный вызов должен иметь возможность принимать разные типы. например. "ColumnTypes"

Что я пробовал:

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);

результат:

.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: примечание: шаблон кандидата проигнорирован: не удалось сопоставить 'function <void (bool, vector <tuple <type-parameter-0-0 ...>, allocator <tuple <type-parameter-0-0 ...>>> &)> 'против' void (*) (bool, std :: vectorstd :: tuple <int, std :: allocatorstd :: tuple <int>> &) 'void PostgresCaller :: query (std :: function <void (bool success, ozo :: rows_of <ColumnTypes ...> & results)> обратный вызов, const std :: string & query, ParameterTypes && ... параметры)

Я также пробовал с лямбдой:

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

результат:

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

.h: 165: 22: примечание: шаблон кандидата проигнорирован: не удалось сопоставить 'function <void (bool, vector <tuple <type-parameter-0-0 ...>, allocator <tuple <type-parameter-0-0 ...>>> &)> 'против' (лямбда в .cpp: 241: 32) 'void PostgresCaller :: query (std :: function <void (bool success, ozo :: rows_of <ColumnTypes ...> & результаты)> обратный вызов, const std :: string & query, ParameterTypes && ... параметры) ^

Это выполнимо и как это сделать? очень признателен. /Джон

Ответы

1 super Dec 18 2020 at 23:02

Вывод шаблона работает только с точным типом, который вы передаете, поэтому, если вы передаете указатель на функцию, шаблон не может определить, в какой тип std::functionпреобразовать этот указатель на функцию.

Сделайте вызываемый параметр шаблоном вместо использования std::function.

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

В большинстве случаев вам не нужно выводить подпись обратного вызова. Просто вызовите его с аргументами, которые вы ожидаете от него.

Если этого недостаточно, есть способы вывести сигнатуру обратного вызова, но он становится немного более подробным и в большинстве случаев не служит реальной цели.