接受std::函数的模板函数,该函数依赖于模板形参
C++11 Template function that takes a std::function which depends of template parameters
我正在尝试编写一个模板函数,该函数接受依赖于模板参数的std::function
。不幸的是,编译器不能正确地推导出std::function
的参数。下面是一些简单的示例代码:
#include <iostream>
#include <functional>
using namespace std;
void DoSomething( unsigned ident, unsigned param )
{
cout << "DoSomething called, ident = " << ident << ", param = " << param << "n";
}
template < typename Ident, typename Param >
void CallFunc( Ident ident, Param param, std::function< void ( Ident, Param ) > op )
{
op( ident, param );
}
int main()
{
unsigned id(1);
unsigned param(1);
// The following fails to compile
// CallFunc( id, param, DoSomething );
// this is ok
std::function< void ( unsigned, unsigned ) > func( DoSomething );
CallFunc( id, param, func );
return 0;
}
如果我用下面的语句调用模板:
CallFunc( id, param, DoSomething );
得到以下错误:
function-tpl.cpp:25: error: no matching function for call to
CallFunc(unsigned int&, unsigned int&, void (&)(unsigned int, unsigned int))
如果我显式地创建一个正确类型的std::函数(或强制转换它),问题就解决了:
std::function< void ( unsigned, unsigned ) > func( DoSomething );
CallFunc( id, param, func );
我该如何编码,使显式临时不需要?
您需要将第三个函数参数作为其中模板参数的非推导上下文。然后,编译器将不会在不考虑所有隐式转换的情况下比较实参类型和形参类型(标准说,c++ 0x进一步澄清了这一点,对于没有模板形参的函数形参,所有隐式转换都被允许弥合差异)。
template < typename T > struct id { typedef T type; };
template < typename Ident, typename Param >
void CallFunc( Ident ident, Param param,
typename id<std::function< void ( Ident, Param ) >>::type op )
{
op( ident, param );
}
你可以用boost::identity
代替id
。在c++ 0x和支持它的编译器中,您可以使用别名模板获得更具可读性的版本
template < typename T > using nondeduced = typename id<T>::type;
那么你的代码变成了简单的
template < typename Ident, typename Param >
void CallFunc( Ident ident, Param param,
std::function< nondeduced<void ( Ident, Param )> > op )
{
op( ident, param );
}
但是GCC还不支持别名模板。
如果你使用的是模板,你可以完全避免使用std::function
,除非出于某种原因你想要特别限制函数只能使用std::function
:
template < typename Ident, typename Param, typename Func >
void CallFunc( Ident ident, Param param, Func op )
{
op( ident, param );
}
您可以内联或使用:bind
进行转换。两者都不是特别漂亮,但它们都能完成工作
CallFunc(id, param, std::function<void(unsigned, unsigned)>(DoSomething));
CallFunc(id, param, std::bind(DoSomething, std::placeholders::_1, std::placeholders::_2));
相关文章:
- 构造函数/函数声明参数列表中的统一初始化
- 如何区分宏函数和函数函数而没有任何歧义?
- 在c++中为链接列表创建复制构造函数/函数
- C++ 使函数调用依赖于模板参数
- 如何声明模板函数,以便可以在类构造函数/函数中传递
- 在C 中,如何调用构造函数函数
- 如何让成员函数实现依赖于类的模板参数?
- bool值不在腔函数函数中重新调整false,c
- 用参数调用函数/函数,而不是参数
- 为什么在破坏函数函数中fstream Zero ernno
- 采用nulltpr_t的构造函数:函数定义不声明参数
- 调用函数函数从功能指针向量向量的函数指针
- Main 不能调用函数:函数未在此范围内声明
- 通过包装器对象的构造函数将依赖关系传递给包装器对象
- 如何调用传递的函数(函数 ptr 作为参数传递给函数)
- C++成员函数的依赖非限定名的两阶段查找
- 为什么构造函数调用依赖于默认析构函数的存在?
- 在c++中,当组合对象构造函数有依赖关系时,如何在初始化列表中强制它们的顺序
- 通过构造函数进行依赖注入的最佳实践
- 用于检查 R 函数是否依赖于 C/C++ 编译代码的函数