How do I remove code duplication between similar const and non-const member functions?

c++, c++-faq, code-duplication, explicit-object-parameter, function-qualifier

Solution

Yes, it is possible to avoid the code duplication. You need to use the const member function to have the logic and have the non-const member function call the const member function and re-cast the return value to a non-const reference (or pointer if the functions returns a pointer):

class X
{
   std::vector<Z> vecZ;

public:
   const Z& z(size_t index) const
   {
      // same really-really-really long access 
      // and checking code as in OP
      // ...
      return vecZ[index];
   }

   Z& z(size_t index)
   {
      // One line. One ugly, ugly line - but just one line!
      return const_cast<Z&>( static_cast<const X&>(*this).z(index) );
   }

 #if 0 // A slightly less-ugly version
   Z& Z(size_t index)
   {
      // Two lines -- one cast. This is slightly less ugly but takes an extra line.
      const X& constMe = *this;
      return const_cast<Z&>( constMe.z(index) );
   }
 #endif
};

NOTE: It is important that you do NOT put the logic in the non-const function and have the const-function call the non-const function -- it may result in undefined behavior. The reason is that a constant class instance gets cast as a non-constant instance. The non-const member function may accidentally modify the class, which the C++ standard states will result in undefined behavior.

Problem

Let's say I have the following `class X` where I want to return access to an internal member: ``` class Z { // details }; class X { std::vector<Z> vecZ; public: Z& Z(size_t index) { // massive amounts of code for validating index Z& ret = vecZ[index]; // even more code for determining that the Z instance // at index is *exactly* the right sort of Z (a process // which involves calculating leap years in which // religious holidays fall on Tuesdays for // the next thousand years or so) return ret; } const Z& Z(size_t index) const { // identical to non-const X::Z(), except printed in // a lighter shade of gray since // we're running low on toner by this point } }; ``` The two member functions `X::Z()` and `X::Z() const` have identical code inside the braces. This is duplicate code and can cause maintenance problems for long functions with complex logic. Is there a way to avoid this code duplication?

Original source

Related problems