简体   繁体   English

是否可以对成员初始化器列表中的不可移动的 object 进行两步初始化?

[英]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.

相关问题 如何返回不可移动(但可复制)的对象? - How do I return a non-movable (but copyable) object? 不可复制、不可移动、显式构造类型的成员数组的初始化 - Initialization of member array of non-copyable, non-movable, explicitly constructed types 在不调用initializer_list构造函数的情况下,将不可复制,不可移动的类型构造为函数参数 - Constructing a non-copyable, non-movable type into a function parameter without invoking initializer_list constructor 为什么不可移动的 Object 仍然是一个副本 - why non-movable Object still a copy 在for循环中声明两个不同的变量,其中一个是不可移动,不可复制的对象 - Declare two different variables in for loop where one is a non-movable, non-copyable object 是否可以返回不可移动,不可复制类型的实例? - Is it possible to return an instance of a non-movable, non-copyable type? 替换不可复制,不可移动的对象 - Replacing a non-copyable, non-movable object 使用显式构造函数返回不可复制的不可移动对象 - Returning non-copyable non-movable object with explicit constructor std :: tuple用于不可复制和不可移动的对象 - std::tuple for non-copyable and non-movable object 构造函数初始化列表中的非成员初始化 - Non-member initialization in constructor initializer list
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM