I am trying to learn computer graphics using the book Interactive computer graphics – A top-down approach, the code of the examples is in this link
There’s a header library called ´mat.h´ that gives some matrix utilities, but when I try to compile with Xcode the following error is thrown:
Non-const lvalue reference to type ‘Angel::mat2’ cannot bind to a temporary of type ‘Angel::mat2’
The piece of code that throws that error is:
mat2& operator /= ( const GLfloat s ) {
#ifdef DEBUG
if ( std::fabs(s) < DivideByZeroTolerance ) {
std::cerr << "[" << __FILE__ << ":" << __LINE__ << "] "
<< "Division by zero" << std::endl;
return mat2();
}
#endif // DEBUG
I just comment it out because it just gets compiled when debugging the app, but I would like to know what’s the problem and how to solve it.
Strictly speaking, while the formal reason for the error is the attempt to bind a non-const reference to a temporary, the real problem here is the very attempt to return a reference, any reference to a temporary object. Whether the reference is const or not does not matter.
The temporary object will be destroyed right after the return statement completes, resulting in a dangling reference bound to a now-destroyed object being returned. In other words, even if we attempt to “fix” this code by changing the return type to const reference, it still won’t work properly.
Moreover, it appears that by design this function is supposed to return a non-const reference, meaning that changing the return type of this function is not an option. A non-const reference is what compound assignment operators typically return. The debug branch is just supposed to terminate early (and, of course, to return something, anything just to make the code compile) in case of “divide by zero” situation.
One way to achieve that is to declare a standalone object of type
mat2(as a static member of classmat2, for example) and return a reference to it. I.e. declaredefine it
and then do
whenever an error is detected.
Alternatively (and much more easily) you can declare it locally right before that
returnstatementOf course, there’s an obvious flaw in this design, since the outside code will be able to modify the returned object, which is undesirable. However, most likely the idea is that the program’s behavior is not guaranteed once an error message is printed to
std::err, meaning that the modifiability of the returned value should not be a problem in this case.Taking that last point into account, we can even use a non-static local variable as a return value
To return a reference to a local variable is as wrong as to return a reference to a temporary (for largely the same reasons). However, within the “no guarantees after an error” approach it will “work”, meaning that it will fix the error message.