将右值引用绑定(bind)到给定对象或其临时拷贝的最佳方法是什么?

A &&var_or_dummy = modify? static_cast<A&&>( my_A )
                         : static_cast<A&&>( static_cast<A>( my_A ) );

(此代码在我最近的GCC 4.6上不起作用。我记得它以前可以工作,但是现在它总是返回一个拷贝。)

在第一行,static_castmy_A从左值转换为x值。 (C++ 0x§5.2.9/1-3)第二行的内部static_cast执行左值到右值转换,而外部的const从此prvalue获得一个xvalue。

这似乎受到支持,因为根据§12.2/5命名的引用有条件地绑定(bind)到临时引用。在带有move引用的C++ 03中,相同的技巧以相同的方式工作。

我也可以不那么冗长地写同样的东西:
A &&var_or_dummy = modify? std::move( my_A )
                         : static_cast<A&&>( A( my_A ) );

现在要短得多。第一个缩写是可疑的:move旨在表示对象正在发生某些事情,而不仅仅是lvalue-to-xvalue-l-value随机播放。令人困惑的是,不能在:之后使用A(my_A),因为该函数调用会中断临时到引用的绑定(bind)。语法static_cast也许比static_cast更清晰,但是从技术上讲,它等效于C风格的强制转换。

我也可以一路走下去,完全用C风格的强制转换编写它:
A &&var_or_dummy = modify? (A&&)( my_A ) : (A&&)( A( my_A ) );

毕竟,如果这将成为一种习惯用法,那么它一定很方便,而且my_A并不能真正保护我免受任何侵害-真正的危险是在true情况下无法直接绑定(bind)到A

另一方面,这很容易被重复三次的类型名所支配。如果将V替换为一个大而丑陋的template-id,我真的想要一个真正的捷径。

(请注意,尽管ojit_code出现了五次,但它仅被评估一次:)
#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 ) ) )

我认为宏是骇人听闻的,是这堆中最好的选择。这有点危险,因为它返回一个xvalue,因此不应在引用初始化之外使用它。

一定有我没想到过的东西……建议?

最佳答案

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

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

代替:
void f(bool modify, A &obj) {
  A &&var_or_dummy = /* ??? */;
  real();
  work();
}

这是lambdas, lambdas, everywhere!

10-06 13:50
查看更多