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_A在true案件中.
另一方面,这很容易被重复三次的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!