我有一个包含几个POD类型和一个字符串成员的结构体。我想使用默认的飞船操作符来允许对我的结构体进行相等操作,但我遇到了一些字符串成员的问题。据我所知,应该有<=>
for std::string
的支持,但实际上似乎并非如此。
我有一个最小的复制例子,以及我从clang(版本14)得到的警告,奇怪的是,在godbolt中这个例子没有产生警告/错误,甚至可以追溯到clang 12(https://godbolt.org/z/b65s9oMGf)。
我真的很感激你能指出我的误解所在,因为我对这个问题很困惑。
#include <compare>
#include <string>
enum class MyEnum
{
ZERO = 0,
ONE = 1
};
struct MyStruct
{
float a{};
int b{};
std::string c{};
MyEnum d{};
auto operator<=>(const MyStruct&) const = default;
};
int main()
{
MyStruct my_struct;
MyStruct my_other_struct;
if(my_struct == my_other_struct)
{
return 0;
}
return 1;
}
$ clang --std=c++20 -Werror test.cpp
test.cpp:16:10: error: explicitly defaulted three-way comparison operator is implicitly deleted [-Werror,-Wdefaulted-function-deleted]
auto operator<=>(const MyStruct&) const = default;
^
test.cpp:13:17: note: defaulted 'operator<=>' is implicitly deleted because there is no viable three-way comparison function for member 'c'
std::string c{};
^
1 error generated.
$ clang --version
Apple clang version 14.0.0 (clang-1400.0.29.202)
1条答案
按热度按时间dxpyg8gm1#
根据评论,这个版本的clang及其标准库似乎:
<=>
的语言功能,但是<=>
实现库添加(特别是为std::string
添加<=>
)。当你写:
默认的
<=>
意味着使用<=>
进行成员间比较,返回第一个比较结果不相等的成员的值。当使用auto
时,这要求编译器为您推导比较类别-但与auto
的典型用法不同(这里所有的返回类型必须相同,auto
推导出一个类型),这里我们取所有比较类别中的最小值。如果有一个成员的<=>
返回weak_ordering
,而另一个成员的<=>
返回strong_ordering
,则默认的<=>
将返回weak_ordering
(而不是不编译)。基本上-它做了你可能想让它做的事情,以你期望的方式。但是--有时默认
<=>
是不够的,如果你的一个成员实际上还没有提供<=>
**(就像在这个例子中).在这种情况下,手动写出所有的比较是很乏味的.因此,有另一种方法可以默认<=>
(从P1186):您可以显式提供比较类别:这意味着,我们不是简单地做成员式的
<=>
,而是做一些更复杂的事情:<=>
,就使用它,并且它必须满足比较类别的要求(在这种情况下,它可能会失败,因为float
与partial_ordering
进行比较,而partial_ordering
不满足strong_ordering
的要求-所以它必须返回partial_ordering
)。<=>
,则我们从==
和<
合成三路比较。因此,在本例中:
会表现为:
这个语言特性的优点(正如我在那篇论文中所阐述的)是,一旦
std::string
确实提供了<=>
,您的实现将自动地获得它,并且更加高效(因为上面的实现对于字符串来说真的不是一个很好的实现,您可能想要做c.compare(rhs.c) <=> 0
),而不必自己做所有的工作。