我有一个无法重新分配的班级。实际动机是它有一个
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};
| ^
有没有办法强制重建而不是重新分配元素?
不,没有办法强制进行不会是未定义行为的重建,至少在不破坏预先存在的元素并使用新放置的情况下是这样。
既然你提到了
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);
}