C++ 为什么'std::可选<;T>;::运算符=`T包含`const`数据成员时删除?

C++ 为什么'std::可选<;T>;::运算符=`T包含`const`数据成员时删除?,c++,c++17,assignment-operator,stdoptional,C++,C++17,Assignment Operator,Stdoptional,以下代码将导致编译器错误: #include <optional> class A { }; class B { private: const A a; }; int main() { B b; std::optional<B> bo1; bo1 = b; } #包括 甲级{ }; B类{ 私人: 常数A; }; int main() { B B; std::可选bo1; bo1=b; } 例如,在gcc上,错误为: main.cp

以下代码将导致编译器错误:

#include <optional>

class A {
};
class B {
private:
    const A a;
};

int main()
{
    B b;
    std::optional<B> bo1;
    bo1 = b;
}
#包括
甲级{
};
B类{
私人:
常数A;
};
int main()
{
B B;
std::可选bo1;
bo1=b;
}
例如,在gcc上,错误为:

main.cpp:在函数“int main()”中:
main.cpp:12:7:错误:“B类”中未初始化的常量成员
12 | B;
|       ^
main.cpp:7:13:注意:“const A B::A”应该初始化
7 |常数A;
|             ^
main.cpp:14:11:错误:使用已删除的函数“std::optional&std::optional::operator=(std::optional&&)”
14 | bo1=b;
|           ^
在main.cpp中包含的文件中:1:
/lib/gcc head/include/c++/12.0.0/optional:663:11:注意:“std::optional&std::optional::operator=(std::optional&&)”被隐式删除,因为默认定义的格式不正确:
663 |等级可选
|           ^~~~~~~~
/lib/gcc head/include/c++/12.0.0/可选:663:11:错误:使用删除的函数“std::_Enable_copy_move&std::_Enable_copy_move::operator=(std:_Enable_copy_move&)[with_Tag std::optional]”
在/lib/gcc head/include/c++/12.0.0/optional:43中包含的文件中,
来自main.cpp:1:
/lib/gcc head/include/c++/12.0.0/bits/enable_special_members.h:248:5:注意:此处声明
248 |运算符=(_Enable_copy_move&&)noexcept=delete;
|     ^~~~~~~~
在MSVC上,作为另一个示例,错误如下:

main.cpp
(14) :错误C2280:'std::optional&std::optional::operator=(const std::optional&'):尝试引用已删除的函数
C:/data/msvc/14.29.29917-Pre/include\optional(445):注意:编译器已在此处生成“std::optional::operator=”
C:/data/msvc/14.29.29917-Pre/include\optional(445):注意:'std::optional&std::optional::operator=(const std::optional&'):函数被隐式删除,因为基类调用了一个已删除或不可访问的函数'std:'u deleted\u move\u assign&std:'u deleted\u move\u assign::operator=(const std:'u deleted\u move\u assign&)'
具有
[
_Ty=B
]
C:/data/msvc/14.29.29917-Pre/include\xsmf_control.h(131):注意:'std:'u Deleted_move_assign&std:'u Deleted_move_assign::operator=(const std:'u Deleted_move_assign&'):函数被隐式删除,因为基类调用了一个已删除或不可访问的函数'std:'u Deleted_copy_assign&std:'u copy_assign&std:'=(const std::_Deleted_copy_assign&)'
具有
[
_Ty=B
]
C:/data/msvc/14.29.29917-Pre/include\xsmf_control.h(92):注意:'std:'u Deleted_copy_assign&std:'u Deleted_copy_assign::operator=(const std:'u Deleted_copy_assign&'):函数被明确删除
具有
[
_Ty=B
]
返回的编译器:2
只要我们删除
const A;
中的
const
关键字,错误就会消失。
根据,有时会根据std::is_…able_v测试删除=运算符的某些重载。在这种情况下,
const
关键字为什么会影响其中一些测试?

在构建对象后不能修改const数据成员。因此,正常工作的
运算符=
是不可更改的可能。

可选
使用对象的
=

无法为具有
const
数据成员的类分配数据。只能构造该类

试试这个:

B b0;    
B b1;
b0=b1;
optional
不起作用,因为
B
不起作用

另外,请尝试
static\u assert(!std::is\u copy\u assignable\u v)
,它会传递

现在,
std::optional
在这里有一个“后门”

B;
std::可选bo1;
bo1.炮位(b);
它构造而不是赋值


从理论上讲,Optional可以回过头来;但是如果内容存在,它需要销毁它,然后放置一个新对象。这是有风险的,会弄乱语义,并且是一个不好的静默计划。

经验法则,永远不要使用
Optional
操作符=
T
在右手边。在我看来,它的语义是不正确的观点,因为它混合了抽象的层次。没有它,毫无疑问有多少事情应该表现出来(比如
T const
T&
)。
B b;
std::optional<B> bo1;
bo1.emplace(b);