【问题标题】:Can I use template type T in std::function to pass a lambda type function C++11?我可以在 std::function 中使用模板类型 T 来传递 lambda 类型函数 C++11 吗?
【发布时间】:2015-12-10 10:59:10
【问题描述】:

我是c++11的新手,我定义了一个模板来接受一个函数作为参数,

template <typename T>
void print_for_each(vector<T> v, std::function<void (T)> func){
    std::for_each(v.begin(), v.end(), func); 
}

我尝试将以下 Lambda 表达式传递给 print_for_each,

auto printElement = [](int y) { 
    std::cout << y << " "; 
}; 

然后我收到编译器警告说,

错误:没有匹配的函数调用“print_for_each”

然后我把模板函数改成,

std::function<void (int)> func)

这次有效。 我的问题是,std::function 可以采用模板类型 T 吗?

感谢您的回答! :)

【问题讨论】:

    标签: c++ templates c++11


    【解决方案1】:

    Lambda std::functions 不同。前者是伪装的函子(函数对象),而后者是另一种野兽。尽管 lambda 可以“衰减”到 std::function,但在模板类型推导中,编译器不执行隐式转换。所以在这种情况下,编译器会尝试匹配两个不兼容类型的对象,因此会失败。

    您可能想知道为什么编译器不执行这种隐式转换。这是因为通过在参数类型推导之上执行类型转换,人们可能会遇到许多“自相矛盾”的情况,其中不止一种不兼容的类型可能是候选者。

    可能的解决方案:

    1. 您可以将函数的签名更改为

      template <typename T, typename F>
      void print_for_each(vector<T> v, F&& func){
          std::for_each(v.begin(), v.end(), func); 
      }   
      
    2. 您可以将 lambda 封装在 std::function 中并将后者传递给您的函数(请参阅 @Brian 的评论)

    3. 您可以“帮助”编译器并显式指定模板类型参数

      print_for_each<int>(v, func);
      

      在这种情况下,没有进行模板类型推导,并且允许 lambda 通过隐式转换衰减到 std::function

    【讨论】:

    • 有一些方法可以解决这个问题。有关示例,请参阅此demo
    • @BrianRodriguez 当然,或者您可以“帮助”编译器并明确指定模板类型参数print_for_each&lt;int&gt;(...)
    • @BrianRodriguez 谢谢你的例子。
    【解决方案2】:

    std::for_each 不需要std::function,只需要一个函子。 您的模板也应该这样做:

    template< typename C, typename F >
    void print_for_each( C& c, F f )
    {
        std::for_each( c.begin(), c.end(), f ); 
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-02
      • 1970-01-01
      • 2013-01-24
      相关资源
      最近更新 更多