Can I avoid more than three levels of indentation?

At work, I recently wrote a smaller operator for a class that was implemented from the published specification and has many properties, six of which are used to uniquely identify an instance of the class. (For the sake of this question, we will call these properties af.) Additionally, these six properties have six different types. I have defined the operator as such:

bool operator<(const Class& lhs, const Class& rhs)
{
    bool retval = (&lhs != &rhs);
    if (retval == true)
    {
        if (lhs.a == rhs.a)
        {
            if (lhs.b == rhs.b)
            {
                if (lhs.c == rhs.c)
                {
                    if (lhs.d == rhs.d)
                    {
                        if (lhs.e == rhs.e)
                        {
                            retval = (lhs.f < rhs.f);
                        } else {
                            retval = (lhs.e < rhs.e);
                        }
                    } else {
                        retval = (lhs.d < rhs.d);
                    }
                } else {
                    retval = (lhs.c < rhs.c);
                }
            } else {
                retval = (lhs.b < rhs.b);
            }
        } else {
            retval = (lhs.a < rhs.a);
        }
    }
    return retval;
}

      

This, of course, violates the coding philosophy of the Linux kernel: "If you need more than three levels of indentation, you're screwed anyway and have to fix your program." So my question is, is there a better way to define this operator so that there are not so many levels of indentation?

+3


source to share


5 answers


You can write such a lexicographic comparison like this:

if (lhs.a != rhs.a) return lhs.a < rhs.a;
if (lhs.b != rhs.b) return lhs.b < rhs.b;
if (lhs.c != rhs.c) return lhs.c < rhs.c;
if (lhs.d != rhs.d) return lhs.d < rhs.d;
if (lhs.e != rhs.e) return lhs.e < rhs.e;
return lhs.f < rhs.f;

      



You can rewrite this with a single return like this:

bool result;
if (lhs.a != rhs.a) result = lhs.a < rhs.a;
else if (lhs.b != rhs.b) result = lhs.b < rhs.b;
else if (lhs.c != rhs.c) result = lhs.c < rhs.c;
else if (lhs.d != rhs.d) result = lhs.d < rhs.d;
else if (lhs.e != rhs.e) result = lhs.e < rhs.e;
else result = lhs.f < rhs.f;
return result;

      

+10


source


You can use std::tie

to perform lexicographic comparisons:



bool operator<(const Class& lhs, const Class& r) {
  return std::tie(lhs.a, lhs.b, lhs.c, lhs.d, lhs.e) < std::tie(rhs.a, rhs.b, rhs.c, rhs.d, rhs.e);
} 

      

+10


source


Since you only install retval

1 time and return it after installation, you can completely uninstall it and use it return

. This, along with reordering your logic, might look like this:

bool operator<(const Class& lhs, const Class& rhs)
{
    if(&lhs == &rhs)
        return false;

    if (lhs.a != rhs.a)
        return (lhs.a < rhs.a);

    if (lhs.b != rhs.b)
        return (lhs.b < rhs.b);

    // And so on...
}

      

+2


source


This is a properly formatted nested ternary statement. It is also one line of execution instruction.

bool operator<( const Class& lhs, const Class& rhs ) const {
    return   lhs.a != rhs.a ? lhs.a < rhs.a
           : lhs.b != rhs.b ? lhs.b < rhs.b
           : lhs.c != rhs.c ? lhs.c < rhs.c
           : lhs.d != rhs.d ? lhs.d < rhs.d
           : lhs.e != rhs.e ? lhs.e < rhs.e
           : lhs.f < rhs.f;
}

// The Above Is The Same As:
bool operator<( const class& lhs, const Class&rhs ) const {
    bool result;
    if (lhs.a != rhs.a) result = lhs.a < rhs.a;
    else if (lhs.b != rhs.b) result = lhs.b < rhs.b;
    else if (lhs.c != rhs.c) result = lhs.c < rhs.c;
    else if (lhs.d != rhs.d) result = lhs.d < rhs.d;
    else if (lhs.e != rhs.e) result = lhs.e < rhs.e;
    else result = lhs.f < rhs.f;
    return result;
}
// The Main Difference Is You Are Not Declaring A Stack Variable To The Compiler
// Nor Are You Using If Else Statements, This Is Handled Automatically By The Compiler
// And This Is Usually Done Within The Registers.

      

+2


source


if (lhs.a != rhs.a) retval = lhs.a < rhs.a; goto end;
if (lhs.b != rhs.b) retval = lhs.b < rhs.b; goto end;
if (lhs.c != rhs.c) retval = lhs.c < rhs.c; goto end;
if (lhs.d != rhs.d) retval = lhs.d < rhs.d; goto end;
if (lhs.e != rhs.e) retval = lhs.e < rhs.e; goto end;
retval = lhs.f < rhs.f
end:
return retval;

      

+1


source







All Articles