C++ 11模板函数,它接受一个取决于模板参数的std :: function

mar*_*ark 5 c++ c++11

我正在尝试编写一个模板函数,它接受一个std::function取决于模板参数的函数.不幸的是,编译器无法正确地将参数deuced到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;
}
Run Code Online (Sandbox Code Playgroud)

如果我使用以下内容调用模板:

CallFunc( id, param, DoSomething );
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

function-tpl.cpp:25:错误:没有匹配的函数用于调用 CallFunc(unsigned int&, unsigned int&, void (&)(unsigned int, unsigned int))

如果我显式创建了一个正确类型的std :: function(或者将其强制转换),问题就会消失:

std::function< void ( unsigned, unsigned ) > func( DoSomething );
CallFunc( id, param, func );
Run Code Online (Sandbox Code Playgroud)

我如何对此进行编码以便不需要显式临时?

Joh*_*itb 8

您需要将第三个函数参数作为其中的模板参数的非推导上下文.然后编译器不会将参数类型与参数类型进行比较而不考虑所有隐式转换(标准说明,并且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 );
}
Run Code Online (Sandbox Code Playgroud)

而不是id你可以使用boost::identity.在C++ 0x和支持它的编译器中,您可以使用别名模板获得更易读的版本

template < typename T > using nondeduced = typename id<T>::type;
Run Code Online (Sandbox Code Playgroud)

然后你的代码变得简单

template < typename Ident, typename Param >
void CallFunc( Ident ident, Param param, 
               std::function< nondeduced<void ( Ident, Param )> > op )
{
    op( ident, param );
}
Run Code Online (Sandbox Code Playgroud)

但是,GCC尚不支持别名模板.


Ale*_*x B 2

如果您使用模板,则可以std::function完全避免,除非出于某种原因您想特别限制要采用的函数std::function:

template < typename Ident, typename Param, typename Func >
void CallFunc( Ident ident, Param param, Func op )
{
    op( ident, param );
}
Run Code Online (Sandbox Code Playgroud)