【问题标题】:Bind a lambda to a function to get return result将 lambda 绑定到函数以获取返回结果
【发布时间】:2014-06-23 23:01:54
【问题描述】:

尝试将 lambda 作为参数传递给采用 std::function 的函数,然后使用类型推导获取返回值。但是编译失败。

#include <future>


class WorkQue
{
    public:
        template<typename R, typename ...Args>
        std::future<R> addItem(std::function<R(Args...)> task, Args... args)
        {
            std::promise<R>     promise;
            std::future<R>      future = promise.get_future();

            // STUFF

            return future;
        }
};

int main()
{
    WorkQue     que;
    int         x = 1;
    int         y = 2;

    // This fails
    que.addItem([](int x, int y){return x+y;}, x, y);

    // I can see needing to specify the return type.
    // But even this does not work.
    // que.addItem<int>([](int x, int y){return x+y;}, x, y);

    // This works fine.
    // But I was hoping not to need to specify this every time.
    //que.addItem<int>(std::function<int(int,int)>([](int x, int y){return x+y;}), x, y);
}

编译错误是:

> g++ -std=c++1y thread.cpp
thread.cpp:24:9: error: no matching member function for call to 'addItem'
    que.addItem([](int x, int y){return x+y;}, x, y);
    ~~~~^~~~~~~
thread.cpp:9:24: note: candidate template ignored: could not match 'function<type-parameter-0-0 (type-parameter-0-1...)>' against '<lambda at thread.cpp:24:17>'
        std::future<R> addItem(std::function<R(Args...)> task, Args... args)
                       ^
1 error generated.

【问题讨论】:

标签: c++ templates lambda template-meta-programming c++14


【解决方案1】:

你不需要使用std::function

class WorkQue
{
    public:
        template<typename Func, typename ...Args>
        auto addItem(Func && task, Args &&... args) -> std::future<decltype(task(std::forward<Args>(args)...))>
        {
            using R = decltype(task(std::forward<Args>(args)...));
            std::promise<R>     promise;
            std::future<R>      future = promise.get_future();

            // STUFF

            return future;
        }
};

http://coliru.stacked-crooked.com/a/c1a8b02a1fbf5123

【讨论】:

  • 最好使用Args &amp;&amp;...decltype(std::forward&lt;Func&gt;(task)(std::forward&lt;Args&gt;(args)...)),完美转发呼叫站点的所有内容。
  • @Mankarse 你是对的。但是有必要在decltype中转发task吗?
  • @BryanChen 我想是的,否则如果无法复制args 之一,decltype 可能格式不正确,您最终会使用 SFINAE 函数(但我我不确定)。无论如何,你可以使用result_of
  • @Bryan Chen:如果 addItem 只用 lambda 调用,则不会。在一般情况下是的,当 operator() 可以被 ref-qualified (example) 时。
  • @Mankarse 感谢您的示例。但我认为它会在代码中添加太多噪音,而在这个答案中几乎没有收获。
猜你喜欢
  • 1970-01-01
  • 2020-09-18
  • 2011-10-01
  • 2015-05-29
  • 1970-01-01
  • 1970-01-01
  • 2019-01-20
  • 2017-02-26
  • 1970-01-01
相关资源
最近更新 更多