[英]Is it possible to do a two-step initialization of a non-movable object in the member initializer list?
Is it possible to do a two-step initialization of a non-movable object in the member initializer list using C++17?是否可以使用 C++17 对成员初始化器列表中的不可移动 object 进行两步初始化?
Here is the legacy API I'm working with (and yes I know it's bad but I can't change it)这是我正在使用的旧版 API(是的,我知道这很糟糕,但我无法更改)
class A {
public:
A(int some_param);
// no default, move or copy constructor nor assignment
A() = delete
A(const& A) = delete;
A(const&&) = delete; // it shouldn’t be deleted, but I’m not able to modify that class
A& operator= (const& A) = delete;
A& operator= (const&&) = delete;
// and it uses two phase construction
void init(int some_other_argument);
// more stuff
};
class B {
public:
// no default constructor, and must be created with a fully-initialized A
B() = delete;
B(const& A);
// more stuff
};
And here is what I am trying to write:这是我想写的:
class C {
public:
C();
private:
A m_a;
B m_b;
};
C::C()
: m_a{ /* two step initialization of A*/}
, m_b(m_a)
{}
The usual trick of using a immediately initialize lambda doesn't work:使用立即初始化 lambda 的常用技巧不起作用:
C::C()
: m_a{[] {
auto a = A(0xdead_beef);
a.init(42);
return a; // doesn’t compile because A isn’t movable
}()}
, m_b(m_a)
{}
Nor does using the body of the constructor:也不使用构造函数的主体:
C::C()
// m_a and m_b will be default-initialized here, but their default initializer are deleted
{
m_a = A(0xdead_beef);
m_a.init();
m_b = B(m_a);
}
And nor doing the second step of the two step initialization in the body of the constructor:也没有在构造函数的主体中执行两步初始化的第二步:
C::C()
: m_a(0xdead_beef)
, m_b(m_a) // m_a isn’t fully initialized here
{
m_a.init();
}
Currently I'm using a unique_ptr
for m_b
, but I was asking myself if there was a better solution.目前我正在为
m_b
使用unique_ptr
,但我在问自己是否有更好的解决方案。
class C {
public:
C();
private:
std::unique_ptr<A> m_a; // guaranted to be initialized in the constructor, no need to check before dereferencing
B m_b;
};
C::C()
: m_a{[] {
auto a = new A(0xdead_beef);
a->init(42);
return a;
}()}
, m_b(*m_a)
{}
I think the rules of guaranteed move elision were improved in C++20, but I'm still using C++17.我认为保证移动省略的规则在 C++20 中得到了改进,但我仍在使用 C++17。
You might still abuse of comma operator:您可能仍然滥用逗号运算符:
C::C() : m_a{ 0xdeadbeef },
m_b((m_a.init(42), m_a))
{}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.