如何构造(而不是分配)std::array 元素?

问题描述 投票:0回答:1

我有一个无法重新分配的班级。实际动机是它有一个

std::variant
成员变量,并且由于有一些引用成员变量(无法反弹),因此可能的类型不可重新分配。这是我们现有的一个非常简单的版本:

class MyClass
{
public:
    MyClass() {}
    MyClass(int a) {}
    MyClass(MyClass &other) = default;
    MyClass(MyClass &&other) = default;
    MyClass &operator=(MyClass &) = delete;
    MyClass &operator=(MyClass &&) = delete;
};

现在,在某个时候,我有一个这些对象的数组。

std::array<MyClass, 5> my_array; // default initializes all objects

最终,我想创建一个新对象并将其放入数组中。

my_array[1] = {69};

但是 std::array 尝试分配,所以我收到错误。

error: use of deleted function ‘MyClass& MyClass::operator=(MyClass&&)’
   29 |     my_array[1] = {69};
      |                      ^

有没有办法强制重建而不是重新分配元素?

c++ constructor assignment-operator stdarray
1个回答
0
投票

不,没有办法强制进行不会是未定义行为的重建,至少在不破坏预先存在的元素并使用新放置的情况下是这样。

既然你提到了

std::variant
:你可以更改元素类型,即使在构造元素之后,无论
std::variant
的元素类型是否可复制/可移动。只需使用
std::variant::emplace

以下示例在

MyClass
中实现赋值运算符,使代码类似于
my_array[1] = {69};
工作。


struct IntHolder
{
    int& m_value;
    IntHolder(int& value)
        : m_value(value)
    {
    }

};

using Variant = std::variant<std::monostate, IntHolder>;

class MyClass
{
    Variant m_member;
public:
    MyClass() {}
    MyClass(int& a)
    {
        m_member.emplace<IntHolder>(a);
    }

    // we'll remove both move and copy semantics for MyClass
    MyClass(MyClass&& other) = delete;
    MyClass& operator=(MyClass&&) = delete;

    // ---- assignment operators for reassigning the variant element ---------

    MyClass& operator=(std::reference_wrapper<int> a)
    {
        m_member.emplace<IntHolder>(a);
        return *this;
    }

    MyClass& operator=(std::monostate)
    {
        m_member.emplace<std::monostate>();
        return *this;
    }

    // ------------------------------------------------------------------------

    friend std::ostream& operator<<(std::ostream& s, MyClass const& value)
    {
        if (std::holds_alternative<IntHolder>(value.m_member))
        {
            s << "{ IntHolder { value = " << std::get<IntHolder>(value.m_member).m_value << " } }";
        }
        else
        {
            s << "{ std::monostate }";
        }
        return s;
    }
};


void Print(std::array<MyClass, 2> const& a)
{
    for (auto& e : a)
    {
        std::cout << e << '\n';
    }
}

int main()
{
    int x = 1;
    int y = 2;

    // initialized with first element refering to x and second one as std::monostate
    std::array<MyClass, 2> arr{ x };

    std::cout << "after initialization\n";
    Print(arr);

    // change frst element to std::monostate and second one to refer to y
    arr[0] = std::monostate{};
    arr[1] = std::ref(y);
    std::cout << "after modification\n";
    Print(arr);
}
© www.soinside.com 2019 - 2024. All rights reserved.