C ++ - std :: bind调用operator(),具有完美的转发功能

时间:2016-07-06 15:44:35

标签: c++ stdbind

我必须存储参数(参数包),并将参数传递给另一个函数 结果,我不能使用lambda。一个很好的选择是std :: bind。

但对于这段代码

struct A{};

void test(A &&){}

int main()
{
    A a;
    test(move(a));    //work
    bind(test,a)();   //compile fail; copy a to std::bind, pass a to test
}

根据标准,存储在std :: bind中的所有变量都将作为lvalue传递给函数。 (C ++标准并没有说,我认为这就是它的意思。)
这意味着我不能使用std :: bind的函数(在参数中有rvalue引用)。

一种解决方案是将test(A &&)更改为test(A &),但这仅适用于您的项目(并且使其变得奇怪,而您不仅需要通过std :: thread调用test而且还需要通过plain调用test顺序呼叫)。

那么,有什么方法可以解决这个问题吗?

1 个答案:

答案 0 :(得分:1)

您可以创建可转换为右值引用的包装器(如reference_wrapper / l-values引用)并将其与bind一起使用:

它看起来像那样:

#include <iostream>
#include <functional>

struct A{};

void test(A &&){ std::cout << "Works!\n"; }

template <typename T>
struct rvalue_holder
{
    T value;
    explicit rvalue_holder(T&& arg): value(arg) {}
    operator T&&()
    {
        return std::move(value);
    }
};

template <typename T>
rvalue_holder<T> rval(T && val)
{
    return rvalue_holder<T>(std::move(val));
}

int main()
{
    A a;
    test(std::move(a));    //work
    auto foo = std::bind(test, rval(std::move(a)));   //works
    foo();
}

http://coliru.stacked-crooked.com/a/56220bc89a32c860

注意:rvalue_holderrval都需要进一步努力,以确保所有情况下的效率,稳健性和理想的行为。