#include <iostream>
using namespace std;


template <typename T>
struct NonConst {typedef T type;};
template <typename T>
struct NonConst<T const> {typedef T type;}; //by value
template <typename T>
struct NonConst<T const&> {typedef T& type;}; //by reference
template <typename T>
struct NonConst<T const*> {typedef T* type;}; //by pointer
template <typename T>
struct NonConst<T const&&> {typedef T&& type;}; //by rvalue-reference

template<typename TConstReturn, class TObj, typename... TArgs>
typename NonConst<TConstReturn>::type likeConstVersion(
   TObj const* obj,
   TConstReturn (TObj::* memFun)(TArgs...) const,
   TArgs... args) {
      return const_cast<typename NonConst<TConstReturn>::type>(
         (obj->*memFun)(args...));
}

struct T {
   int arr[100];
   int const& getElement(size_t i) const{
      return arr[i];
   }
   int& getElement(size_t i) {
      return likeConstVersion(this, &T::getElement, i);
   }
   /*
   int const& getElement() const{
      return 42;
   }
   int& getElement() {
      return likeConstVersion(this, &T::getElement);
   }*/
};

int main() {
	T t;  
	int b=t.getElement(4);
	return 0;
}