问题标签 [spaceship-operator]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - 为什么宇宙飞船操作员不允许我执行相等操作但允许不等式操作?
有谁知道为什么我在具有 3 路运算符覆盖的类上的相等操作出现编译器错误?我正在使用 VS 2019。
我收到上述行的错误: NativeConsoleApp.cpp(68,20): error C2676: binary '==': 'Rectangle' does not defined this operator or a conversion to an type接受预定义的运算符
编辑:请注意非默认运算符 <=> 的解释不会生成 == 和 C++20 中的 !=并没有解决不等式运算符有效但相等运算符无效的原因。
编辑:一个月后重读后,上面的链接现在有意义了。
c++ - C++20 行为用相等运算符破坏现有代码?
我在调试这个问题时遇到了这个问题。
我一直将其修剪为仅使用Boost Operators:
-
该程序可以在 GCC 和 Clang 中使用 C++17(启用 ubsan/asan)编译和运行良好。
当您将隐式构造函数更改为 时
explicit
,有问题的行显然不再在 C++17 上编译
令人惊讶的是,这两个版本都在 C++20 (v1和v2)上编译,但它们导致在 C++17 上无法编译的两行上的无限递归(崩溃或紧密循环,取决于优化级别)。
显然,这种通过升级到 C++20 潜入的无声 bug 令人担忧。
问题:
- 这是否符合 c++20 行为(我希望如此)
- 究竟是什么干扰?我怀疑这可能是由于 c++20 的新“宇宙飞船操作员”支持,但不明白它如何改变这段代码的行为。
c++ - C++20 宇宙飞船运算符的性能问题?
从 C++20 开始,标准库使用spaceship 运算符来实现字符串和向量的比较(根据此视频)。我担心这会带来潜在的巨大性能损失!
让我解释一下运算符的!=
示例string
:
- 当我编写
str1 != str2
时,编译器现在将其转换为(str1 <=> str2) != 0
. - 然而,一个有效的
!=
for实现string
将首先检查 forstr1.size() != str2.size()
,并且只有在失败时才转移到比较实际字符。 - 这种优化无法为 spaceship 运算符实现,因为无论如何它都必须确定“更大”的字符串。
因此,如果这确实是现在比较字符串的不等式,这不是巨大的性能损失吗?
c++ - 继承的综合比较运算符产生警告/错误:ISO C++20 考虑使用重载运算符 '!='
在以下代码片段中,clang 11.0.1 生成警告
实时代码: https ://godbolt.org/z/65zWEq
上面的代码可以使用 Visual C++ (VS 16.8.x) 和以前的预览版 (VS 16.9.0 Preview 2) 成功编译。但是,最近发布的 VS 16.9.0 Preview 3 现在会为此代码片段产生错误:
看起来没有为iterator
具有 CRTP 类的派生类提供综合比较运算符的合规方法iterator_facade
吗?
c++ - 模棱两可的重载运算符 C++20
我正在尝试在最新的 Visual Studio 和 Clang 版本中测试我的项目。弹出的错误之一与不明确的运算符有关(with reversed parameter order)
。这似乎没有在 C++17 中弹出。
例如:(https://godbolt.org/z/Gazbbo)
我不确定为什么这会是一个问题。在我看来,这里唯一可行的功能是bool operator==(const B& other) const
asA
可以隐式转换为B
但不能反过来。事实上,如果我用标记代替B(const A&)
,explicit
我会得到一个B
无法转换为A
.
我试图了解我可以做些什么来避免这种情况,除了使用explicit
或使用B(a)
. 想象一下A
,B
如果是库代码,我如何在不破坏低版本界面的情况下支持 C++20?
c++ - MSVC 的标准库没有为 std::string、std::shared_ptr 等定义 spaceship 运算符?
我正在尝试使我的程序多平台,最初是为 Linux 编写的。MSVC(我使用的是 19.28)被告知从 19.20 版(https://en.cppreference.com/w/cpp/compiler_support/20)开始支持宇宙飞船操作员,但它似乎没有为 std 定义这个操作员::string 或 std::shared_ptr (可能适用于许多其他生物)。
我真正想做的是:
现场示例: https ://godbolt.org/z/Eo49hh
它在 GCC 10.2 下工作。我在这里遗漏了一些观点,还是没有完全支持?
c++ - 为什么 std::tuple 调用运算符 <=> 两次?
以下代码调用运算符 <=> 两次,参数颠倒。但为什么?
GCC 10.2 和 clang 12 似乎都在使用 libstdc++-10,其 <tuple> 确实提供了运算符 <=>,因此这似乎不是缺少标准库支持的情况,而且我的代码必须不正确。如何解决?
c++ - 为什么 spaceship 允许混合比较(不同的模板实例化)与无意义的结果?
编辑:这与宇宙飞船无关。只是使用 spaceship 混淆了我的代码中的真正问题(有关详细信息,请参阅答案)。
我对这个程序的输出感到惊讶:(如果您喜欢谜题,请随时打开 Godbolt 链接并尝试自己找出原因)
输出:
假
假
假
假
在指责了Godbolt缓存之后......我发现问题在于我正在比较TotallyOrdered<float>
和TotallyOrdered<double>
(在给出预期输出f
之后添加)。1234.567
我的问题是:
- 为什么允许这样做?(不问这是否是标准行为;它是,但对设计意图感到好奇。)
- 为什么比较没有给出strong_ordering中的“枚举”?尽管我只定义了
strong_order
<=>
. - 如何强制仅“精确 +-cvref”比较(给出
std::strong_ordering
结果)编译,防止给出的比较std::partial_ordering
?
c++ - 为什么 C++20 中的空结构没有隐式宇宙飞船运算符?
动机:有时我使用 std::variant 来实现“花式”枚举,其中一些枚举状态可以携带状态。
现在,如果我想<=>
为我的变体使用它,它需要我的空结构已定义 <=>。这对我来说似乎有点奇怪,因为如果类型的状态位为 0,则该类型的所有实例都是相同的。
完整示例:
c++ - 使用 C++20 三向比较进行更静默的行为变化
令我惊讶的是,我遇到了另一个障碍,比如C++20 行为用相等运算符破坏现有代码?.
考虑一个简单的不区分大小写的键类型,与例如std::set
or一起使用std::map
:
简单测试:
使用 C++17,两个断言都通过(编译器资源管理器)。
切换到 C++20,第二个断言失败(编译器资源管理器)
output.s: ./example.cpp:28: int main(): Assertion `mappings.size() == 3' 失败。
明显的解决方法
一个明显的解决方法是operator<=>
在 C++20 模式下有条件地提供:编译资源管理器
问题
令我惊讶的是,我遇到了另一种破坏性更改的情况——C++20 在没有诊断的情况下更改了代码的行为。
在我阅读std::tuple::operator<
它时应该有效:
3-6)按字典顺序比较
lhs
,即比较第一个元素,如果它们等价,则比较第二个元素,如果它们等价,则比较第三个元素,依此类推。对于非空元组,(3) 等价于rhs
operator<
我知道从技术上讲,这些从 C++20 开始就不再适用,它被替换为:
通过综合三向比较(见下文)按字典顺序进行比较
lhs
,rhs
即比较第一个元素,如果它们相等,比较第二个元素,如果它们相等,比较第三个元素,依此类推
和...一起
<、<=、>、>= 和 != 运算符分别由
operator<=>
和合成operator==
。(C++20 起)
事情是,
我的类型没有定义
operator<=>
也不operator==
,并且正如这个答案所指出的那样,提供
operator<
额外的东西会很好,并且应该在评估简单的表达式时使用,比如a < b
.
- C++20 中的行为更改是否正确/故意?
- 应该有诊断吗?
- 我们可以使用其他工具来发现像这样的无声破损吗?感觉就像扫描整个代码库以在
tuple
/中使用用户定义的类型pair
并不能很好地扩展。 tuple
除了/之外,还有其他类型pair
可以表现出类似的变化吗?