1

The comparison operator== for std::array, as provided by the standard library, works only for arrays of equal size. E.g., the following code does not compile

#include <array>

int main()
{
   std::array<int, 2> a{1, 3};
   std::array<int, 3> b{1, 2, 3};
   bool x = (a == b);
}

It seems logical to define a comparison between arrays of unequal size as being always false. By the standard, however, one is not allowed to overload operator== for the non user-defined types. There is always the option of defining a compare function like

template <typename U, std::size_t N, std::size_t M>
bool compare(const std::array<U, N>& a, const std::array<U, M>& b) noexcept
{
    if constexpr (N == M) {
       return (a == b);
    }
    else {
       return false;
    }
}

Such a solution is unconvenient, since it means that one has to always use the syntax compare(a, b) when there is the chance that a and b have different sizes.

  • Is there a fundamental reason why the standard library does not define operator== as in the code above?

  • Is there a better solution for comparing unequal-sized arrays?

francesco
  • 7,189
  • 7
  • 22
  • 49
  • Can you expand on what you mean by not being allowed to overload `operator==`? What exactly forbids you from writing your `compare` function template as a non-member `operator==`? Multiple definition of `operator==` for equal-sized arrays? – Nathan Pierson Aug 01 '21 at 20:56
  • `std::array` of different size are different type, and it seems to me like the standard library doesn't usually provide overloads for all possible types of containers. For example, it doesn't provide `operator==(const std::vector&, const std::deque&)`. It provides `std::equal` instead. If you want to compare unrelated ranges, use `std::equal`. The comparison will probably be optimized out for `std::array` of different sizes. – François Andrieux Aug 01 '21 at 20:57
  • You could wrap (by inheritance) in class that only adds extra operators you want – M.M Aug 01 '21 at 20:58
  • @NathanPierson The standard allows operator overloading only for user-defined types, see [operator overloading](https://en.cppreference.com/w/cpp/language/operators) and [this answer](https://stackoverflow.com/a/4421715/8769985) – francesco Aug 01 '21 at 21:02
  • @francesco `std::array` is a user-defined type in this sense. See footnote 1 in your second link. – Nathan Pierson Aug 01 '21 at 21:03
  • @NathanPierson uhm, I thought that types of the standard library are not "user-defined type". Do you have a link to the reference or to the standard that says that? – francesco Aug 01 '21 at 21:11
  • 1
    An array size is part of its type. How did it come to this that you need to compare objects of different types? Do you compare vector to maps, too? :) – rustyx Aug 01 '21 at 21:12
  • You can define a new operator overload but you cannot put it in `std::` namespace so no ADL. The link is slighlty wrong AFAIK, [this](https://timsong-cpp.github.io/cppwp/n3337/over.match.oper#2) is the only condition required for overloading of operators. There was an issue with the usage of the term "user-defined" in the Standard - [Issue 2139](https://cplusplus.github.io/LWG/issue2139). Also I can see how this issue can arise in generic code quite easily. – Quimby Aug 01 '21 at 21:29
  • 1
    @francesco Standard library types are technically user-defined types because they aren't core language features. But it is often useful to treat them as non-user-provided for the purpose of that rule, because function and operator overloads that only contain built-in and standard types are good candidates for multiple definitions errors. A typical example is implementing `operator<<(std::ostream&, const std::vector&)`. It's legal, but what happens if two developers (maybe from different libraries you use) implement it and don't agree on what it should do. – François Andrieux Aug 01 '21 at 21:41
  • What if I want to essentially zero-extend the shorter array (out to the length of the longer) for the purpose of comparing if they are equal? Or maybe I _don't_ want to compare two different length arrays, and want the compilation error (because they are different types)? Neither of those possibilities would be allowed if two different length arrays would compare as unequal. – 1201ProgramAlarm Aug 01 '21 at 21:56
  • "It seems logical to define a comparison between arrays of unequal size as being always false" No it absolutely totally definitely doesn't seem logical at all. If you need to compare objects of different types, why restrict this to just arrays with the same element type? Why not arrays of different element types? Why not different containers? Why not different arbitrary types? A string is always unequal to an mutex, why not define comparison this way? – n. m. could be an AI Aug 02 '21 at 05:07

1 Answers1

1

Is there a fundamental reason why the standard library does not define operator== as in the code above?

Most fundamental reason that standard library doesn't define it is: Such operator== wasn't proposed. This is the proposal to add the wrapper into the standard. It does not contain rationale for not providing comparison between different instances of the template. There's no evidence in the document that such operator had been even considered.

eerorika
  • 232,697
  • 12
  • 197
  • 326