Question

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

In the following example :

template<typename Type, unsigned int Size>
class MyClass
{
    public: inline Type& operator[](const unsigned int i) 
    {return _data[i];}

    public: inline const Type& operator[](const unsigned int i) const
    {return _data[i];}   

    protected: Type _data[Size];
};

the const and non-const operator[] are implemented independently.

In terms of design is it better to have :

  • 1) two independant implementations like here
  • 2) one of the two function calling the other one

If solution 2) is better, what would be the code of the given example ?

Was it helpful?

Solution 2

You couldn't have either implementation calling the other one without casting away constness, which is a bad idea.

The const method can't call the non-const one.

The non-const method shouldn't call the const one because it'd need to cast the return type.

OTHER TIPS

It is a well-known and widely accepted implementation pattern, when non-const method is implemented through its const counterpart, as in

 class some_class {

   const some_type& some_method(arg) const
   {
     ...;
     return something;
   }

   some_type& some_method(arg)
   {
     return const_cast<some_type&>(
       const_cast<const some_class *>(this)->some_method(arg));
   }
 };

This is a perfectly valid technique, which essentially has no comparable (in convenience) alternatives in situations when the method body is relatively heavy. The evil of const_cast is significantly smaller than the evil of duplicated code.

However, when the body of the method is essentially an one-liner, it might be a better idea to stick to an explicit identical implementation, just to avoid this barely readable pileup of const_casts.

One can probably come up with a formally better designed castless solution implemented along the lines of

 class some_class {

   template <typename R, typename C>
   static R& some_method(C *self, arg)
   {
     // Implement it here in terms of `self->...` and `R` result type
   }

   const some_type& some_method(arg) const
   {
     return some_method<const some_type>(this, arg);
   }

   some_type& some_method(arg)
   {
     return some_method<some_type>(this, arg);
   }
 };

but to me it looks even less elegant than the approach with const_cast.

Unfortunately, "constness" templates don't work but I still think it is worth considering the overall idea:

// NOTE: this DOES NOT (yet?) work!
template <const CV>
Type CV& operator[](unsigned int index) CV {
    ...
}

For the time being, I'd implement trivial functions just twice. If the code become any more complex than a line or two, I'd factor the details into a function template and delegate the implementation.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top