Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Could I have avoided more than 3 levels of indentation?

At work I recently wrote a less than operator for a class implemented from a published specification and which has many properties, six of which are used to uniquely identify an instance of the class. (For the sake of this question, we'll call these properties a-f.) Also, these six properties are of six different types. I 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, breaks the Linux kernel coding philosophy of, "If you need more than 3 levels of indentation, you're screwed anyway, and should fix your program." So my question is, is there a better way to define this operator to not have so many levels of indentation?

like image 888
LowTechGeek Avatar asked Nov 27 '22 16:11

LowTechGeek


2 Answers

You can write this kind of lexicographical 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 re-write 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;
like image 76
Brian Bi Avatar answered Dec 19 '22 04:12

Brian Bi


You can use std::tie to do lexicographical 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);
} 
like image 39
Chris Drew Avatar answered Dec 19 '22 04:12

Chris Drew