函数接受函数作为模板类型的参数

Posted

技术标签:

【中文标题】函数接受函数作为模板类型的参数【英文标题】:Function accepting functions as parameter with templated types 【发布时间】:2021-03-29 06:11:47 【问题描述】:

我对编程和 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...>> 

我希望为每个查询提供一个回调,这个回调需要能够接受不同的类型。例如。 “列类型”

我尝试过的:

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, allocator > > &)>' 反对 'void (*)(bool, std::vectorstd::tuple > &)' void PostgresCaller::query(std::function& results)> 回调, const std::string& query, ParameterTypes&& ... 参数)

我也尝试过使用 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);

结果:

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

.h:165:22:注意:候选模板被忽略:无法匹配 'function, allocator > > &)>' 对 '(lambda at .cpp:241:32)' void PostgresCaller::query(std::function& results)> 回调, const std::string& query, ParameterTypes&& ... 参数) ^

这可行吗?如何实现?非常感激。 /约翰

【问题讨论】:

query 期望 std::function 作为第一个参数。你传递的东西不是std::function 的特化。模板参数推导不考虑隐式转换。您必须在呼叫站点将回调包装成合适的std::function。或者重新设计query 以接受任意可调用对象,如果您可以控制它。 【参考方案1】:

模板推导仅适用于您传入的确切类型,因此如果您传入函数指针,模板无法推导出将函数指针转换为哪种std::function

使可调用的模板参数,而不是使用std::function

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

大多数时候你不需要推断回调的签名。只需使用您希望它采用的参数调用它即可。

如果这还不够,也有一些方法可以推断出回调的签名,但它会变得有点冗长,而且大部分时间都没有实际用途。

【讨论】:

以上是关于函数接受函数作为模板类型的参数的主要内容,如果未能解决你的问题,请参考以下文章

如何将使用参数包和类型名的类作为函数的输入参数(c++)

从std :: function中推导返回和参数类型作为模板函数参数传递?

C++ 模板(进阶)

c++ 模板

如何模板化一个接受模板化参数并在 C++ 中对其应用模板化函数的函数?

C++模板非类型模板参数