我想在没有不必要的移动或复制的情况下取出临时成员.
假设我有:
class TP {
T _t1, _t2;
};
Run Code Online (Sandbox Code Playgroud)
我想得到_t1
,_t2
来自TP()
.没有复制/移动成员是否可能?
我尝试过使用元组并试图"转发"(我认为不可能)成员,但我能得到的最好的是一个动作,或者成员立即死亡.
在下面的操场中使用B::as_tuple2
最终会员过早死亡,除非结果绑定到非ref类型,否则会移动成员.在客户端,B::as_tuple
简单的移动是安全的auto
.
我认为这应该在技术上是可行的,因为临时死亡,并且成员在他们可以绑定到调用站点上的变量时死亡(我错了吗?),并且类似结构的结构化绑定按预期工作.
是否可以将成员的生命延长/传递到外部变量,或者忽略移动/复制?我需要它与c ++ 14版本,但我无法让它在c ++ 17上工作,所以我对两者都感兴趣.
游乐场:
#include <tuple>
#include <iostream>
using std::cout;
class Shawty {
/**
* Pronounced shouty.
**/
public:
Shawty() : _id(Shawty::id++) {cout << _id << " ctor\n"; }
Shawty(Shawty && s) : _id(Shawty::id++) { cout << _id << " moved from " << s._id << "\n"; }
Shawty(const Shawty & s) : _id(Shawty::id++) { cout << _id << " copied from " << s._id << "\n"; }
Shawty& operator=(Shawty && s) { cout << _id << " =moved from " << s._id << "\n"; return *this;}
Shawty& operator=(Shawty & s) { cout << _id << " =copied from " << s._id << "\n"; return *this;}
~Shawty() {cout << _id << " dtor\n"; }
int _id;
static int id;
};
int Shawty::id = 0;
class B {
public:
auto as_tuple() && {return std::make_tuple(std::move(_s1), std::move(_s2));}
auto as_tuple2() && {return std::forward_as_tuple(std::move(_s1), std::move(_s2));}
private:
Shawty _s1, _s2;
};
struct S {
Shawty _s1, _s2;
};
int main() {
std::cout << "----------\n";
auto [s1, s2] = B().as_tuple2();
std::cout << "---------\n";
auto tpl1 = B().as_tuple2();
std::cout << "----------\n";
std::tuple<Shawty, Shawty> tpl2 = B().as_tuple2();
std::cout << "----------\n";
std::cout << std::get<0>(tpl1)._id << '\n';
std::cout << std::get<1>(tpl1)._id << '\n';
std::cout << std::get<0>(tpl2)._id << '\n';
std::cout << std::get<1>(tpl2)._id << '\n';
std::cout << s1._id << '\n';
std::cout << s2._id << '\n';
std::cout << "--struct--\n";
auto [s3, s4] = S{};
std::cout << s3._id << '\n';
std::cout << s4._id << '\n';
std::cout << "----------\n";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
不可以。不可能将多个成员的生命周期延长到超出超级对象的生命周期。
因此,在不复制的情况下“获取”成员的唯一方法是保持超级对象处于活动状态,并引用它们:
// member function
auto as_tuple3() & {
return std::make_tuple(std::ref(_s1), std::ref(_s2));
}
// usage
B b;
auto [s1, s2] = b.as_tuple3();
Run Code Online (Sandbox Code Playgroud)
通过将引用绑定到单个成员来延长对象生命周期的示例。请注意,这要求可以从绑定引用的位置访问该成员(不是您的示例中的情况,其中该成员是私有的):
auto&& s1 = B{}._s1;
Run Code Online (Sandbox Code Playgroud)