2
votes

im fairly new to programming and C++. I have a function that i want to accept function-pointers with templated values as argument. Here is what i mean...

i have this function:

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" is alias for:

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

I want each query to be provided with a callback, this callback will neeed to be able to accept different types. eg. "ColumnTypes"

What i've tried:

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

result:

.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: note: candidate template ignored: could not match 'function<void (bool, vector<tuple<type-parameter-0-0...>, allocator<tuple<type-parameter-0-0...> > > &)>' against '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&& ... parameters)

I also tried with 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);

result:

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

.h:165:22: note: candidate template ignored: could not match 'function<void (bool, vector<tuple<type-parameter-0-0...>, allocator<tuple<type-parameter-0-0...> > > &)>' against '(lambda at .cpp:241:32)' void PostgresCaller::query(std::function<void(bool success, ozo::rows_of<ColumnTypes...>& results)> callback, const std::string& query, ParameterTypes&& ... parameters) ^

Is this doable and how can it be done? much appreciated. /John

1
query expects std::function as the first parameter. You are passing things to it that are not specializations of std::function. Template parameter deduction doesn't consider implicit conversions. You'd have to wrap the callback into a suitable std::function at the call site. Or else redesign query to accept an arbitrary callable, if you have control over it.Igor Tandetnik

1 Answers

1
votes

Template deduction only works on the exact type that you pass in, so if you pass in a function pointer the template can't deduce what kind of std::function to convert that function pointer to.

Make the callable a template parameter, instead of using std::function.

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

Most of the time you don't need to deduce the signature of the callback. Just call it with the arguments you expect it to take.

If this is not enough, there are ways to deduce the signature of the callback as well, but it gets a bit more verbose and most of the time serves no real purpose.