Tre*_*key 14 c++ move-semantics perfect-forwarding c++11 stdtuple
我正在看一些代码,我看到以下功能:
template <typename... Args>
static return_t make_return(Args &&... args)
{
// using std::forward<Args> will preserve lvalue args as such, but the point of this function
// is to make a return, where the 99.9+% case is moving a local (lvalue) into the return pack.
// Thus it forces a move, which will move `T&` args (but _not_ `const T&` args) into the
// return pack so that users don't need to type out a bunch of std::moves themselves/
// If they don't want implicit move they can just call std::make_tuple directly
return std::make_tuple(std::move(args)...);
}
Run Code Online (Sandbox Code Playgroud)
这里的文档让我很困惑.
为什么要明确移动转发引用?
您不想在通用上下文中保留左值/右值吗?
我无法理解基本原理或这种行为与推荐的不同之处std::forward.
换句话说,
我从未见过有人明确选择退出完美转发转发参考.
是否有意义?
为什么要明确移动转发引用?
因为它没有用于其转发属性.是的,你是对的,我们通常std::forward是转发参考.但在这种情况下,作者只是为了方便而使用转发引用.如果它被写成make_return(Args&... args)那么就不可能传递rvalue make_return,因为非const左值引用可能不会绑定到一个.
通过使用转发引用,作者允许将任何值类别的值传递到函数中,而不需要额外的副本(如果不需要).文档是为了澄清函数签名不是用于转发,而是简单地绑定到它移出的任何参数.
一个小例子揭示了作者的意图:
#include <tuple>
#include <iostream>
struct A {
A() { }
A(const A&) { std::cout << "copy\n"; }
A(A&&) { std::cout << "move\n"; }
};
template <typename Arg>
static std::tuple<A> make_return(Arg&& arg) {
return std::make_tuple(std::move(arg));
}
void f(const std::tuple<A>&) { }
void f1() {
std::cout << "return local via make_tuple: ";
A a{};
f(std::make_tuple(a));
}
void f2() {
std::cout << "return local via make_tuple(move): ";
A a{};
f(std::make_tuple(std::move(a)));
}
void f3() {
std::cout << "return local via make_return: ";
A a{};
f(make_return(a));
}
void f4() {
std::cout << "return const via make_tuple: ";
const A a{};
f(std::make_tuple(a));
}
void f5() {
std::cout << "return const via make_tuple(move): ";
const A a{};
f(std::make_tuple(std::move(a)));
}
void f6() {
std::cout << "return const via make_return: ";
const A a{};
f(make_return(a));
}
int main() {
f1();
f2();
f3();
f4();
f5();
f6();
}
Run Code Online (Sandbox Code Playgroud)
输出:
return local via make_tuple: copy
return local via make_tuple(move): move
return local via make_return: move
return const via make_tuple: copy
return const via make_tuple(move): copy
return const via make_return: copy
Run Code Online (Sandbox Code Playgroud)
在返回局部非常量变量的情况下,我们想要std::move它的内容。这是可以实现的std::make_tuple(std::move(a)),因为普通std::make_tuple(a)会复制。为了节省一些输入,作者将 写make_return为 的简写std::make_tuple(std::move(a)):示例显示其f3工作方式与f2.
当一个常量被传递时,std::move不会有任何区别,但也没有坏处。所以我们可以使用std::make_tuple, 但也能make_return正常工作。Case f4, f5, 的f6行为都相同,这表明在将常量和非常量混合在一起之前并不需要三思而后行make_return(在多个条目构成 的情况下return_t)。
剩下的就是移动一个非函数局部的非常量变量,因此我们不想破坏它的内容。在这些情况下make_return是不需要的,需要求助于手动调用std::make_tuple(仅std::move在适当的情况下使用)。
现在这会是什么样子std::forward?改变make_return利用的定义
std::make_tuple(std::forward<Arg>(arg));
Run Code Online (Sandbox Code Playgroud)
产生:
return local via tuple: copy
return local via tuple(move): move
return local via make_return: copy
return const via tuple: copy
return const via tuple(move): copy
return const via make_return: copy
Run Code Online (Sandbox Code Playgroud)
因为ainf3作为const A&. 事实上,make_return根据转发的逻辑,它只是 的同义词std::move,失去了我们希望获得的任何好处。
| 归档时间: |
|
| 查看次数: |
505 次 |
| 最近记录: |