3

I have a class, say, vector<T>. I want to implement two getter methods, returning T& and const T& respectively. I do not want to implement both of them. Instead I'd like to implement only const version and then reuse its code in a non-const method with const_cast.

template<typename T>
class Vector {
public:
    T& operator[](size_t i) {
        return const_cast<T&>(
            static_cast<const Vector<T>*>(this)->operator[](i));
    }

    const T& operator[](size_t i) const {
        return data[i];
    }

private:
    T* data;
};

What are the possible pitfalls of this approach? Or, are there any methods to check that const_cast is legitimate in any exact case?

Finally, what are the good common ways to deal with such duplicated const/non-const code?

Ivan Smirnov
  • 4,365
  • 19
  • 30
  • 1
    looks to me like more work and a worse maintenance headache than simply implementing the operator twice – Richard Hodges Mar 15 '17 at 11:26
  • *"Finally, what are the good common ways to deal with such duplicated const/non-const code?"* already has been asked and answered often enough on SO, I suggest you remove that. – Baum mit Augen Mar 15 '17 at 11:27
  • 1
    Related to [elegant-solution-to-duplicate-const-and-non-const-getters](http://stackoverflow.com/questions/856542/elegant-solution-to-duplicate-const-and-non-const-getters) – Jarod42 Mar 15 '17 at 11:31
  • The main reasoning which helped is that the caller of non-const method has a non-const instance of my class, thus const_cast-ing is fine. – Ivan Smirnov Mar 15 '17 at 14:57

1 Answers1

5

One clean way is to delegate to a private template function which can deduce the constness of this:

#include <cstdint>

template<typename T>
class Vector {
public:
    T& operator[](std::size_t i) {
      return impl_indirection(this, i);
    }

    const T& operator[](std::size_t i) const {
      return impl_indirection(this, i);
    }

private:
  template<class MaybeConstVector>
    static decltype(auto) impl_indirection(MaybeConstVector* pv, std::size_t index)
  {
    return pv->data[index];
  }

  T* data;
};
Richard Hodges
  • 68,278
  • 7
  • 90
  • 142