为啥允许将 std::optional 与值进行比较? [复制]
Posted
技术标签:
【中文标题】为啥允许将 std::optional 与值进行比较? [复制]【英文标题】:Why std::optional is allowed to be compared to value? [duplicate]为什么允许将 std::optional 与值进行比较? [复制] 【发布时间】:2021-07-23 00:48:03 【问题描述】:能够比较std::optional<T>
和T
的相等性非常有用:
std::optional<int> opt_value;
int value = 123;
opt_value == value; // will always be 'false'
我认为这种情况下的行为定义明确且清晰。
我不明白为什么允许这样做:
opt_value < value; // this will always be 'true'
我期待这甚至无法编译。 我认为这里发生的事情非常模糊。 STL 中添加了这个的原因是什么?
【问题讨论】:
@JDługosz 正如我所说,我希望它甚至无法编译 这样你就可以拥有一个std::optional
的容器,并对其进行排序。或者在需要订购时使用std::optional
。
@JDługosz 确切地说,我认为使nullopt
总是小于任何其他值是完全任意的。由于许多这些不明显的默认行为通常不会进入标准,我想知道为什么这个特定的行为可以代替。
我不明白是什么让opt_value == value
(对于支持operator==
的值类型比opt_value < value
(对于支持operator<
的值类型)在语义上更有意义),可能的例外是感觉比nullopt_t != value
更“明显”,而 null 可选值和实际值的顺序并不是那么直观。但是“空可选值小于所有值”在 imo 中并不奇怪。
@nyarlathotep108:“是一种非常隐晦的晦涩行为。”我不同意。如果要比较未参与的optional<T>
,则只有两个答案:小于所有T
s,或大于所有T
s。
【参考方案1】:
简答:map<optional<int>, int>
当T
可用作键时,您希望能够将optional<T>
用作map
键。将 empty 状态定义为小于或大于正常值使其表现良好。
同时,比较一个普通的 T
和一个 optional<T>
应该只是,从逻辑上讲,将纯 T
升级为一个 optional<T>
持有该值。因此,提供一个采用裸 T
的重载表单只是一种优化,应该具有相同的结果。
【讨论】:
当可选本质上,它可以让您更轻松地比较值。有了这个你就不用写了:
opt_value.value() < value;
它还会检查以确保 opt_value
具有值。
【讨论】:
我知道这很实用,但我更愿意在这种情况下写更多。这就是重点:在大多数情况下,我更喜欢显式而不是隐式,除非行为非常明显。【参考方案3】:介绍optional
to C++ states the conceptual idea of the type的提案。 optional<T>
是一个对象,它增加了对象类型T
一个附加值:nullopt
。这就是类型的想法;这是一个T
,可以有一个额外的值。
鉴于此推理,如果订购了T
,那么也应该订购optional<T>
。所以现在的问题不是是否应该做到这一点,而是如何做到这一点。
该答案是任意的,但只有两个合理的答案:“不是T
”小于T
的所有值,或者大于T
的所有值。他们选择了前者。
【讨论】:
听起来像是一个武断的决定。我宁愿不为类型定义任意运算符 这也是任意的,但这是 C 的遗产(strcmp 已经存在,所以它是有道理的)。也许本世纪我们可以做得更好。 当然,对于绝大多数可选到可选的比较,它根本不是任意的,因为它遵循值类型的底层比较。是否应该仅仅因为nullopt_t
小于 0
而不是大于或不可比 0
有点武断而牺牲所有这些?
奇怪的是nullopt
小于INT_MIN
。我确实同意能够比较事物是有价值的,但是一个命名的比较器(optional_cmp
?)会有用处,并且不会破坏人们的期望(你会知道你在注册什么)。
这对我来说并不奇怪。 INT_MIN
小于所有其他 ints
,但我们预计它不会小于 LONG_MIN
或 -DBL_MAX
。是最小的int
,不是最小的std::optional<int>
或其他类型。以上是关于为啥允许将 std::optional 与值进行比较? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
为啥 std::optional 不允许“移动构造和仅复制分配”类型的移动分配?
为啥 std::optional 构造函数使用 std::in_place?
为啥 std::optional::value() &&;返回 &&?
`std::optional` 比 `std::shared_ptr` 和 `std::unique_ptr` 有啥优势?
为啥 const rvalue 限定 std::optional::value() 返回 const rvalue 引用?