比较不同大小的数组

5

我正在为了娱乐和学习而实现自己的boost :: array变体,我想知道:比较两个不同大小的数组应该返回false,还是应该是类型错误?

array<int, 3> a = {1, 2, 3};
array<int, 5> b = {1, 2, 3, 4, 5};

a == b   // <--- false or type error?

2
是的,应该这样做。说实话,对于这个问题并没有一个通用的答案 -- 有时你需要进行词汇比较,而其他时候则是明显的逻辑错误。 - Jerry Coffin
@Jerry:词法比较会暗示第三种可能的结果:true。然而,我并不认为两个大小不同的数组相等。 - fredoverflow
如果只是为了好玩和学习,那就两者兼顾。 - Lee Louviere
1
至少对于问题的小变化,我可以看到“true”是一个合理的答案。在图形学中,您经常使用矩阵进行转换。一个3x3矩阵可以转换为产生相同转换的4x4矩阵。对于某些目的来说,认为这两个是相等的是相当合理的。 - Jerry Coffin
7个回答

5
这应该是一种类型错误。使用boost::array的人选择它而不是std::vector,因为他们希望在编译时进行评估(和失败),而不是运行时。

一个总是返回 false 的内联 op== 会对性能产生什么不利影响? - Fred Nurk
@Fred:完全不是,我重新表达了答案。 - Björn Pollex
@Fred:当然我无法知道。但是我可以陈述我的推理,然后让他决定要使用什么(并让其他用户决定是否同意)。 - Björn Pollex
1
@Space_C0wb0y:如果这个答案是您的推理依据,那么这就是循环逻辑;换句话说:“Fred应该决定一个类型错误,因为将使用Fred的数组的人会因为它在这种情况下有一个类型错误而使用它。” - Fred Nurk
1
@Fred:我在回家的路上想了想,得出了同样的结论。如果其他比较是在运行时评估的(因为数组中的值不是编译时常量),那么在运行时评估这种特殊情况将是不一致的。 - Björn Pollex
显示剩余8条评论

4

这个问题没有普适的答案。它取决于比较数组的代码的业务逻辑。

但是一般来说,如果我不知道比较数组的业务逻辑,我会返回false。如果它们的大小不同,那么这两个数组就不同。


1

我认为这个问题比单独的==运算符更普遍。

==运算符与!=紧密相关,可能还与<><=>=有关。

定义应该在所有这些运算符中保持一致,即无论使用什么比较方式,都可以比较两个不同大小的数组,或者不能。

我怀疑两者都可能有用:

  • 编译时错误:您会收到警告,表示这里有些可疑的东西
  • 运行时错误:您不必专门处理不同大小的模板方法。

但只有一个在编译期间产生警告,另一个则意味着您希望通过测试在运行时发现问题。因此,我会提供一个“安全”的运算符重载和一个更详细的“软”比较方法:

template <typename T, size_t M, size_t N>
bool soft_equal(array<T,M> const& lhs, array<T,N> const& rhs)
{
  if (M != N) { return false; }
  // comparison logic
}

template <typename T, size_t M>
bool operator==(array<T,M> const& lhs, array<T,M> const& rhs)
{
  return soft_equal(lhs,rhs); // count on the compiler to eliminate the 'if'
}

我认为这样做可以兼顾两个方面:

  • 编译时可以警告不慎的错误
  • 如果意图明确,编译时的错误可以很容易地避免

指导原则:让正确变得容易,让错误变得困难


1

如果您的数组没有公开基类,例如array<int>,则应该返回类型错误,因为您的类函数基于强类型。如果允许大小多态性,则返回false。

更重要的是,拥有一个在所有情况下始终返回相同值的运算符的好处是什么?


1
在语言中,不同的模板实例化是不相关的类型。这意味着从技术上讲,最简单的方法就是像boost::array一样忽略这个问题,如果你尝试比较不同大小的数组,编译器会报错。
我倾向于回答这取决于您正在建模的领域,但考虑到数组大小是编译时常量,用户应该知道两个数组是不同的,甚至不需要尝试进行比较。即使在模板化代码中,只要有一个单一的大小参数,一切都会自然而然地落到位。

1
在C++中,array<int, 3>array<int, 5>是不同的类型,就像std::vector<int>std::list<int>是不同的类型一样。它们从相同的模板实例化的事实大多是无关紧要的。
现在,您可以将它们都视为序列,然后进行比较会有意义。但是,通常使用迭代器来实现这一点。

虽然它们是不同的类型,但这并不一定排除比较,即使它很“可怕”。 - Fred Nurk
@Fred:不,它不会。但这应该是一个提示,不要使用operator=()来做这件事。 - sbi

0

不同大小的数组是不相等的,在您的情况下,您在编译时就已经知道了。不要为不同大小实现相等运算符;那是毫无意义的!您已经知道它们不相等了!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接