绑定对象或虚拟引用的样式

Pot*_*ter 5 c++ coding-style rvalue-reference c++11

将rvalue引用绑定到给定对象或其临时副本的最佳方法是什么?

A &&var_or_dummy = modify? static_cast<A&&>( my_A )
                         : static_cast<A&&>( static_cast<A>( my_A ) );
Run Code Online (Sandbox Code Playgroud)

(这段代码在我最近的GCC 4.6上不起作用......我记得它之前有效,但现在它总是返回一个副本.)

在第一行,从左值到x值的static_cast变换my_A.(C++0x§5.2.9/ 1-3)static_cast第二行的内部执行左值到右值的转换,外部的第二行从该prvalue获得xvalue.

这似乎得到支持,因为命名引用有条件地绑定到临时符合§12.2/ 5.同样的技巧在C++ 03中以相同的方式使用const引用.

我也可以不那么冗长地写同样的东西:

A &&var_or_dummy = modify? std::move( my_A )
                         : static_cast<A&&>( A( my_A ) );
Run Code Online (Sandbox Code Playgroud)

现在它要短得多.第一个缩写是有问题的:move应该表示对象发生了某些事情,而不是仅仅是左值到左右值的左值.令人困惑的是,move之后无法使用:因为函数调用会中断临时引用绑定.语法A(my_A)可能比static_cast它更清晰,但它在技术上等同于C风格的强制转换.

我也可以一路走下去,完全用C风格的演员阵容写出来:

A &&var_or_dummy = modify? (A&&)( my_A ) : (A&&)( A( my_A ) );
Run Code Online (Sandbox Code Playgroud)

毕竟,如果这将成为一个成语,它必须是方便的,static_cast并不是真的保护我无论如何 - 真正的危险是没有直接绑定my_Atrue案件中.

另一方面,这很容易被重复三次的typename占据主导地位.如果A用一个大而丑陋的模板ID替换,我真的想要一个真正的捷径.

(请注意,V尽管出现了五次,但仅评估一次:)

#define VAR_OR_DUMMY( C, V ) ( (C)? \
  static_cast< typename std::remove_reference< decltype(V) >::type && >( V ) \
: static_cast< typename std::remove_reference< decltype(V) >::type && >   (  \
  static_cast< typename std::remove_reference< decltype(V) >::type >( V ) ) )
Run Code Online (Sandbox Code Playgroud)

作为宏的Hackish,我认为这是最好的选择.它有点危险,因为它返回一个xvalue,因此它不应该在引用初始化之外使用.

必须有一些我没想过的东西...建议?

小智 2

只需通过额外的函数调用来避免整个混乱:

void f(bool modify, A &obj) {
  return [&](A &&obj) {
    real();
    work();
  }(modify ? std::move(obj) : std::move(A(obj)));
}
Run Code Online (Sandbox Code Playgroud)

代替:

void f(bool modify, A &obj) {
  A &&var_or_dummy = /* ??? */;
  real();
  work();
}
Run Code Online (Sandbox Code Playgroud)

到处都是lambda,lambda