【问题标题】:C++ variadic template std::function to lambda conversion not working [duplicate]C ++可变参数模板std :: function到lambda转换不起作用[重复]
【发布时间】:2014-06-05 18:24:37
【问题描述】:

我有以下代码(简化):

#include <functional>
template <typename... Args> void Callback(std::function<void(Args...)> f){
    // store f and call later
}
int main(){
    Callback<int, float>([](int a, float b){
        // do something
    });
}

这样做的目的是获取一些额外的参数、发送数据包、处理响应并使用结果调用 lambda 问题是,它不需要 lambda。

# g++ -std=c++11 test.cpp
test.cpp: In function ‘int main()’:
test.cpp:8:3: error: no matching function for call to ‘Callback(main()::<lambda(int, float)>)’
test.cpp:8:3: note: candidate is:
test.cpp:2:34: note: template<class ... Args> void Callback(std::function<void(Args ...)>)
test.cpp:2:34: note:   template argument deduction/substitution failed:
test.cpp:8:3: note:   ‘main()::<lambda(int, float)>’ is not derived from ‘std::function<void(Args ...)>’

有没有什么方法可以让它工作而无需通过将 lambda 显式包装在 std::function 中的麻烦?

Callback(std::function<void(int, float)>([](int a, float b){
    // do something
}));

即使省略回调模板参数(如此处所示),也可以完美运行。 不过仍然有“额外的”std::function。

为什么它不能自己计算出转换?它适用于非模板:

void B(std::function<void(int, float)> f){/* ... */};
int main(){
    B([](int a, float b){
        // do something
    });
}

供参考,我正在使用

gcc 版本 4.7.2 (Debian 4.7.2-5)

【问题讨论】:

  • 仅仅因为 lambda 可转换为 std::function 并不意味着它 std::function。编译器应该如何从不相关的类型中找出std::function 模板参数?
  • this 会回答您的问题吗?还是this?
  • @Praetorian:如果函数不包含模板参数(如上所述),它可以做到这一点,所以它应该(我认为)也适用于这种情况
  • 模板参数推导 is 出错的地方,所以如果你把它排除在等式之外,它当然可以工作。阅读我在之前评论中链接到的答案。
  • @Praetorian:非常感谢! :)

标签: c++ templates c++11 lambda variadic-templates


【解决方案1】:

您可以使用专用演员表。一旦你有了这样的工具

#include <functional>

using namespace std;

template<typename T>
struct memfun_type
{
    using type = void;
};

template<typename Ret, typename Class, typename... Args>
struct memfun_type<Ret(Class::*)(Args...) const>
{
    using type = std::function<Ret(Args...)>;
};

template<typename F>
typename memfun_type<decltype(&F::operator())>::type
FFL(F const &func)
{ // Function from lambda !
    return func;
}

您可以对所有 lambda 类型说 FFL() 以将它们转换为 std::function 的正确版本

int main()
{
    Callback(FFL([](int a, float b){
        // do something
    }));

    return 0;
}

Display

【讨论】:

    【解决方案2】:

    正如Praetorian 指出的那样:this 回答了我的问题。 我真的很困惑为什么你需要使用suck a hack。 参考代码:

    #include <functional>
    template <typename T> struct identity
    {
      typedef T type;
    };
    template <typename... Args> void Callback(typename identity<std::function<void(Args...)>>::type f){
        // store f and call later
    }
    int main(){
        Callback<int, float>([](int a, float b){
            // do something
        });
    }
    

    像魅力一样工作。

    【讨论】:

      【解决方案3】:

      当 lambda 是非捕获时,您可以使用:

      template <typename L> void Callback(L l){
          using F = typename std::remove_pointer<decltype(+l)>::type;
          std::function<F> f( l );
          // store f and call later
      }
      

      允许您调用:

      Callback([](int a, float b){
          // do something
      });
      

      Live example

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-10
        • 2021-06-30
        • 2015-08-24
        • 1970-01-01
        • 2014-01-03
        • 2022-01-05
        相关资源
        最近更新 更多