2016-07-06 84 views
0

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

但对于这个代码完美转发的C++ 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的将被传递作为左值的功能。 (C++标准没有这样说,我认为这就是它的意思。)
这意味着我不能在std :: bind中使用一个函数(在参数中有rvalue引用)。

一个解决方案是将test(A &&)更改为test(A &),但这只适用于您的项目(并且使它很奇怪,而您不仅需要通过std :: thread调用测试,还需要通过简单的顺序调用来测试)。

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

+4

*“我不能使用拉姆达”*,你能详细说明一下吗?你提到的参数包在哪里? –

+0

@NathanOliver你忘了打电话给'foo' –

+0

@PiotrSkotnicki好点。我做到了,它失败了。 – NathanOliver

回答

1

您可以创建包装,将可转换为右值引用(如reference_wrapper/L值引用),并与bind使用它:

它CAL看起来像:

#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都需要进一步的工作来确保所有情况下的效率,稳健性和所需的行为。

+0

太好了。但我可能不会使用这个解决方案。谢谢。 – Caesar