繁体   English   中英

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

[英]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:错误:没有用于调用CallFunc(unsigned int&, unsigned int&, void (&)(unsigned int, unsigned int))匹配函数CallFunc(unsigned int&, unsigned int&, void (&)(unsigned int, unsigned int))

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

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

而不是id你可以使用boost::identity 在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)); 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM