Comparing arrays of different size
I am implementin开发者_如何学Pythong my own boost::array
variant for fun and education, and I was just wondering: should comparing two arrays of different size yield false, or should it be a type error?
array<int, 3> a = {1, 2, 3};
array<int, 5> b = {1, 2, 3, 4, 5};
a == b // <--- false or type error?
It should be a type-error. People that use boost::array
choose it over std::vector
because they want evaluation (and failure) at compile-time rather than run-time.
There cannot be a general answer to this question. It depends on the business logic of the code that is comparing the arrays.
But in general, if I don't know what the business logic is that's comparing the arrays, I'd return false
. The arrays are different if they aren't the same size.
In the language, the different template instantiations are unrelated types. That means that technically, the simplest thing to do is what boost::array does: ignore the problem, the compiler will yell if you try to compare different sizes.
I was inclined to answer that this depends on the domain that you are modeling, but given that the array size is a compile time constant, the user should know that both arrays are different without even trying to compare. Even in templated code, as long as there is a single size parameter everything would fall into place by itself.
If your array does not expose a base class such as array<int>
, then yield a type error as your class's function is based on strong typing. If you do allow for polymorphism in the size, then return false.
More to the point, what is the benefit of having an operator that in all cases will always return the same value?
I think the issue is more general than the sole ==
operator.
The ==
operator is intimately tied to !=
, and possibly tied to <
, >
, <=
and >=
.
The definition should be consistent among all of them, that is either it is possible to compare two arrays of different size (whatever the comparison used) or it is not.
I suspect that both could be useful:
- compile-time error: you're warned that there is something fishy here
- runtime-time false: you don't have to specialize all your template methods to deal with different sizes.
But only one yields a warning during the compilation, the other implies that you hope to discover the issue at runtime (through testing). Therefore I'd provide a "safe" operator overload, and a more verbose method for the "soft" comparison:
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'
}
This way, you get the best of both worlds, I think:
- The unwary is warned at compilation
- The compile-time error can be worked around easily if it's intended
Guideline: make it easy to get it right, and hard to get it wrong
In C++, array<int, 3>
and array<int, 5>
are different types, just as std::vector<int>
and std::list<int>
are different types. The fact that they are instantiated from the same template is mostly irrelevant.
Now, you can view both as sequences and then comparison would make sense. To do this, however, iterators are commonly used.
Arrays of different sizes are not equal, and in your case you know it at compile-time. Don't implement the equality operator for different sizes; that's pointless! You know that they're not equal already!
精彩评论