如何使用 std::shared_ptr 构建结构的 std::optional
How to construct a std::optional of a struct with std::shared_ptr
我正在尝试创建一个带有 class 的可选项,它有一个 shared_ptr
但隐式删除的构造函数阻止我使用 make_optional
来创建它。
手动编写该构造函数是唯一的选择吗?
这是一个简单的复制:
https://onlinegdb.com/DcWzF1NAt
#include <optional>
#include <memory>
class A
{
public:
A(int v):
val{v}
{}
int val;
};
class B
{
public:
B(std::shared_ptr<A>& a):
a{a}
{}
const std::shared_ptr<A> a;
};
int main()
{
std::shared_ptr<A> a = std::make_shared<A>(3);
std::optional<B> b;
b = std::make_optional<B>(a);
}
导致这个编译错误
main.cpp:31:30: error: use of deleted function ‘std::optional& std::optional::operator=(std::optional&&)’
b = std::make_optional<B>(a);
^
In file included from main.cpp:4:0:
/usr/include/c++/7/optional:453:11: note: ‘std::optional& std::optional::operator=(std::optional&&)’ is implicitly deleted because the default definition would be ill-formed:
class optional
^~~~~~~~
/usr/include/c++/7/optional:453:11: error: use of deleted function ‘std::_Enable_copy_move& std::_Enable_copy_move::operator=(std::_Enable_copy_move&&) [with _Tag = std::optional]’
In file included from /usr/include/c++/7/optional:43:0,
from main.cpp:4:
/usr/include/c++/7/bits/enable_special_members.h:246:5: note: declared here
operator=(_Enable_copy_move&&) noexcept = delete;
^~~~~~~~
不是隐式删除的构造函数导致的问题,是隐式删除的复制赋值运算符,与std::shared_ptr
无关,是因为你声明了B::a
成员为const
。这里的解决方法是不标记为const
:
class B
{
public:
B(std::shared_ptr<A>& a):
a{a}
{}
std::shared_ptr<A> a;
};
编译器删除复制赋值运算符的原因是因为它必须能够修改该成员;我们可以通过一个稍微简单一点的例子来了解这一点:
class NoCopyAssign {
public:
NoCopyAssign(int a) : mA(a) {}
private:
const int mA;
};
通常情况下,复制赋值运算符大致等同于:
NoCopyAssign &operator=(const NoCopyAssign &other) {
mA = other.mA;
return *this;
}
但是这是不可能的,因为 mA
是一个 const int
,所以你不能改变它的值。
};
我正在尝试创建一个带有 class 的可选项,它有一个 shared_ptr
但隐式删除的构造函数阻止我使用 make_optional
来创建它。
手动编写该构造函数是唯一的选择吗?
这是一个简单的复制:
https://onlinegdb.com/DcWzF1NAt
#include <optional>
#include <memory>
class A
{
public:
A(int v):
val{v}
{}
int val;
};
class B
{
public:
B(std::shared_ptr<A>& a):
a{a}
{}
const std::shared_ptr<A> a;
};
int main()
{
std::shared_ptr<A> a = std::make_shared<A>(3);
std::optional<B> b;
b = std::make_optional<B>(a);
}
导致这个编译错误
main.cpp:31:30: error: use of deleted function ‘std::optional& std::optional::operator=(std::optional&&)’
b = std::make_optional<B>(a);
^
In file included from main.cpp:4:0:
/usr/include/c++/7/optional:453:11: note: ‘std::optional& std::optional::operator=(std::optional&&)’ is implicitly deleted because the default definition would be ill-formed:
class optional
^~~~~~~~
/usr/include/c++/7/optional:453:11: error: use of deleted function ‘std::_Enable_copy_move& std::_Enable_copy_move::operator=(std::_Enable_copy_move&&) [with _Tag = std::optional]’
In file included from /usr/include/c++/7/optional:43:0,
from main.cpp:4:
/usr/include/c++/7/bits/enable_special_members.h:246:5: note: declared here
operator=(_Enable_copy_move&&) noexcept = delete;
^~~~~~~~
不是隐式删除的构造函数导致的问题,是隐式删除的复制赋值运算符,与std::shared_ptr
无关,是因为你声明了B::a
成员为const
。这里的解决方法是不标记为const
:
class B
{
public:
B(std::shared_ptr<A>& a):
a{a}
{}
std::shared_ptr<A> a;
};
编译器删除复制赋值运算符的原因是因为它必须能够修改该成员;我们可以通过一个稍微简单一点的例子来了解这一点:
class NoCopyAssign {
public:
NoCopyAssign(int a) : mA(a) {}
private:
const int mA;
};
通常情况下,复制赋值运算符大致等同于:
NoCopyAssign &operator=(const NoCopyAssign &other) {
mA = other.mA;
return *this;
}
但是这是不可能的,因为 mA
是一个 const int
,所以你不能改变它的值。
};