rvalue引用是否有reference_wrapper <>?

Joh*_*itb 13 c++ rvalue-reference stdbind c++11

我想知道如何做到以下几点

void f(string &&s) { 
  std::string i(move(s)); 
  /* other stuff */ 
} 

int main() { 
  std::string s; 
  bind(f, s)(); // Error.
  bind(f, move(s))(); // Error.
  bind(f, ref(s))(); // Error.
}
Run Code Online (Sandbox Code Playgroud)

如何传递rvalue引用并将其作为rvalue引用(可能包装)存储在调用包装器中?我知道我可以手动编写一个类似于std::reference_wrapper<>具有转换功能的类T&&,但我宁愿避免这种情况并使用标准技术.


我像AProgrammer推荐的那样实现了它:

template<typename T> struct adv { 
  T t; 
  explicit adv(T &&t):t(forward<T>(t)) {} 
  template<typename ...U> T &&operator()(U &&...) { 
    return forward<T>(t); 
  } 
}; 

template<typename T> adv<T> make_adv(T &&t) { 
  return adv<T>{forward<T>(t)}; 
}

namespace std { 
  template<typename T> 
  struct is_bind_expression< adv<T> > : std::true_type {}; 
} 
Run Code Online (Sandbox Code Playgroud)

现在我可以说

void f(string &&s) { 
  std::string i(move(s)); 
  /* other stuff */ 
} 

int main() { 
  std::string s; 
  bind(f, make_adv(move(s)))(); // Works!
}
Run Code Online (Sandbox Code Playgroud)

如果我们传递一个左值make_adv,它会将它转发为一个引用输入参数的左值,因此std::ref在这种情况下它可以用作替换值.

APr*_*mer 7

我对此有所了解.

N3225中的20.8.10.1.2/10

绑定参数v1,v2,...,vN及其对应类型V1,V2,...,VN的值取决于从绑定调用派生的TiD类型和调用包装器g的cv限定符cv如下:

  • 如果TiD是reference_wrapper,则参数为tid.get(),其类型Vi为T&;
  • 如果is_bind_expression :: value的值为true,则参数为tid(std :: forward(uj)...),其类型Vi为result_of :: type;
  • 如果is_placeholder :: value的值j不为零,则参数为std :: forward(uj),其类型Vi为Uj &&;
  • 否则,该值为tid,其类型Vi为TiD cv&.

因此,具有右值参考的唯一可能性是具有is_bind_expression<TiD>::value真或is_placeholder<TiD>::value非零.第二种可能性具有您不想要的含义并且实现想要的结果,第一种可能性意味着如果我们限制标准提供的类型,我们试图解决的问题就会得到解决.因此,唯一的可能性是提供您自己的包装器和专门化is_bind_expression<TiD>(由20.8.10.1.1/1允许),因为我没有看到.


sel*_*tze 6

如何传递右值引用并将其存储为调用包装器中的右值引用?

这里的问题是可以多次调用这样的绑定函数对象.如果函数对象将绑定参数转发为rvalue,那么这显然只能工作一次.所以,这是一个安全问题.

但在某些情况下,这种转发正是您想要的.你可以使用lambda作为中介:

bind([](string& s){f(move(s));},move(s));
Run Code Online (Sandbox Code Playgroud)

基本上,我想出了这个绑定+ lambda组合作为缺少"移动捕获"的解决方法.

  • 关于它不是多次可以调用的好点. (2认同)