Preferred implementation of `Array::operator=(const Array & rhs)` I have a custom template class Array&lt;T&gt;, and am currently implementing the assignment operator.

However, I've come across a design decision: When assigning two arrays, must I require them to have the same size, or adjust the LHS Array size to the RHS?



Pros and Cons of Requiring Equal Size

Pro


Most of the time, the array is often thought of as a static container (there are std::vector, etc. for dynamic containers).
It's more efficient, because I do not have to reallocate; rather, I overwrite each element of the LHS.


Con


It's a hassle for the user to do the work himself if he does intend to have a variable-length Array, plus it would be inefficient.




Code

Here are the implementations of the two versions I'm considering.

Equal Size

template &lt;typename T&gt;
bool JKArray&lt;T&gt;::operator=(const JKArray&lt;T&gt; &amp; rhs)
{
    if (this == *rhs) { return true; }
    else
    {
        if (size_ != rhs.size_) { return false; }
        else
        {
            for (int i = 0; i &lt; size_; i++) { array_[i] = rhs.array_[i]; }
        }
    }
}


Unequal Size

template &lt;typename T&gt;
void JKArray&lt;T&gt;::operator=(const JKArray&lt;T&gt; &amp; rhs)
{
    if (this == *rhs) { }
    else
    {
        if (size_ != rhs.size_)
        {
            delete [] array_;
            size_ = rhs.size_;
            array_ = new T[size_];
        }
        for (int i = 0; i &lt; size_; i++) { array_[i] = rhs.array_[i]; }
    }
}


Note

Regarding the implementation of Equal Size: I return false if the size is not equal, and true otherwise. Of course, I could use exceptions, however this is satisfactory for now.



I'm leaning towards making operator= fail* if RHS is a different length than LHS.

I'd like to know what other's have done, and what the prefer. To avoid closing this on the basis of opinion-based, please give explanations as to why one might be preferred over the other.



*See 'Note' under 'Code'.
template &lt;typename T&gt;
bool JKArray&lt;T&gt;::operator=(const JKArray&lt;T&gt; &amp; rhs)

template &lt;typename T&gt;
void JKArray&lt;T&gt;::operator=(const JKArray&lt;T&gt; &amp; rhs)


Neither of them have the correct signature for a copy assignment. The correct signature for that operator is class_name &amp; class_name :: operator= ( const class_name &amp; ).

That already rules out abusing the return value to signal success or failure. If you want runtime errors, you got to do it with exceptions.

If you violate that signature, it makes common patterns such as chained assignment (a = b = c = {...};) impossible. This may break other templated libraries depending on your datatypes to adhere to the standards.

Especially returning a bool may cause rather unexpected side effects.




  Pro
  
  
  Most of the time, the array is often thought of as a static container (there are std::vector, etc. for dynamic containers).
  It's more efficient, because I do not have to reallocate; rather, I overwrite each element of the LHS.
  
  
  Con
  
  
  It's a hassle for the user to do the work himself if he does intend to have a variable-length Array, plus it would be inefficient.
  


That list is by no means complete. There are more aspects to cover:


Iterator invalidation

When you have to re-allocate the backing data structure, it would be trivial to keep all existing iterators valid for same-size copies, while the same feat is problematic for different sizes.
Heap vs stack allocation

For fixed size arrays, it's not even necessary to allocate them on the heap, sufficiently small arrays may as well be allocated straight on the stack. This is obviously impossible to do with the dynamically sized ones.
Array or Vector?

While you call it Array, if you make it re-sizable it behaves more like an std::vector rather than an std::array.
Size as part of the type?

As @Olzhas mentioned, it's an option to include the size of the backing array as a template parameter. This provides compile time checks for compatible or incompatible sizes. Whereby compile time checks - if applicable - are obviously to be preferred.

This would actually be how std::array does it.