采用依赖于模板参数的 std::function 的 C++11 模板函数

标签 c++ c++11

我正在尝试编写一个接受依赖于模板参数的 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::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 );
}

您可以使用 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 的 C++11 模板函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7608741/

相关文章:

c++ - 暗示返回值不被存储的方法

C++:将 UTF16 字符的十六进制表示形式转换为十进制(如 python 的 int(hex_data, 16))

c++ - Utf-8 编码 visual studios 十进制值

c++11 - 使 std::initializer_list const 改变什么?

c++ - 在方法名之前或之后放置 const、static 和 virtual?

c++ - caml_hash_varian返回的值在什么范围?

c++ - 为什么 std::partition 没有异位变体?

c++ - 如何正确启动进程并转发 stdin/stdout/stderr?

c++ - 将右值作为非常量引用传递(VS 警告 C4239)

c++ - 使用 Boost::Interprocess 在进程之间共享 std::string