0

Let's say I had an operator() overload that made temp_.matrix[k][j] and temp_(k+1, j+1) equivalent. In my class functions (where matrix belongs), would it be better to have

if (temp_.matrix[k][j] == 0) { /**do stuff*/ }

or

if (temp_(k+1, j+1) == 0) { /**do stuff*/ }

?

I like using the vanilla version. But the operator() version because it encapsulates the data inside the operator, which we use to access it. I'm not too sure if I'm correct in using the vanilla version due to this reasoning.

  • 4
    I'm going to point out that most style questions are either purely opinion, or dictated by your local style guide. – user40980 May 4 '15 at 18:57
  • 1
    Ending names with _ is fairly uncommon, though it's often used as a prefix for member variables. – Panzercrisis May 4 '15 at 19:07
  • 2
    @Steve314: Only if it begins with double-underscore or underscore followed by uppercase letter. Well, in C++ double-underscore counts too. – Deduplicator May 4 '15 at 21:42
  • @Deduplicator - You're correct - It looks like I've taken the "Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace." from C++ and "All identifiers that begin with an underscore are always reserved for use as identifiers with file scope in both the ordinary and tag name spaces." from C and forgotten that they don't apply to smaller scopes (such as within a class/struct). Comment deleted. – Steve314 May 4 '15 at 22:26
4

Use operator overloading if it improves code clarity and maintainability.

  • Sometimes it helps clarity and maintainability: a + b is shorter and clearer than a.addTo(b), it makes it easier to write generic algorithms (e.g., templates) and change data types, etc.
  • Sometimes it hurts clarity and maintainability: overloaded operators can be surprising (surprising behavior, surprisingly expensive, etc.), it can be harder to find callers, etc.

Keep in mind that "operator overloading versus raw member access" isn't a binary decision; you can also use explicitly named functions (e.g., temp_.get(k, j)). Additionally:

  • Does temp_ do anything besides holding a matrix?
    • If temp_ is a matrix, then the fact that the matrix is a two-dimensional array should be encapsulated (whether via an overloaded operator or an explicit getter function).
    • If temp_ is not a matrix, then the entire matrix should be encapsulated (whether via an overloaded operator or an explicit getter function, with matrix changed to a private member variable).
  • Why use k+1,j+1 for operator() but k, j for matrix[][]? If the indexes are really supposed to be different depending on how the array is accessed, then that suggests a failure of encapsulation.
  • One can easily hide the actual implementation behind a facade with proxy-objects. So [][] delegates, using a proxy-object, to (). – Deduplicator May 4 '15 at 21:45
0

A more fundamental question is whether to define the operator() (by the class) for this purpose or not. Alas, this decision has already been made by the author(s) of the matrix class, so we should consider its usage to be compatible with the intent of the author(s).

Indeed, this is what most matrix (or multi-dimensional array) libraries would choose to implement in C++.


Note that your first version of code may not be future-proof. There is no guarantee that Matrix.matrix exists in future versions of the library, or that Matrix matrix; mat.matrix[k][j] continues to be a valid expression due to future library changes.

Possibilities why such future breaking changes might happen:

  • The matrix library used to have compile-time constant (template-parameterized) matrix sizes, but was later upgraded to support run-time matrix sizes.
    • This means internally it is no longer declaring the matrix as T matrix[M][N]; anymore.
  • The matrix library used to maintain an array of pointers to the start of each row, but then decided to eliminate that in order to save a little bit of memory.
    • This means internally it is no longer declaring matrix as T** matrix;, therefore the field may have been removed, or that you cannot use matrix[row] to get the starting pointer to a particular row.
  • The matrix library may have implemented type erasure, therefore the class no longer knows the type of T at compile-time; instead, it only contains an untyped pointer to the start of the allocated memory block, as in void* matrix; or uchar* matrix;, where uchar has no relationship to the numeric type of the matrix.

However, if the matrix library is under your full control, that is: you wrote it, nobody else can change it, and you have sole discretion on what future changes to be made to it, then the "future-proof" issue does not apply to you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.