#include <iostream>
#include <type_traits>
using namespace std;

template<typename FROM, typename TO>
struct CopyConstImpl {
	using type = typename std::remove_const<TO>::type;
};

template<typename FROM, typename TO>
struct CopyConstImpl<const FROM, TO> {
	using type = typename std::add_const<TO>::type;
};

template<typename FROM, typename TO>
struct CopyConst {
	using type = typename CopyConstImpl<typename std::remove_reference<FROM>::type, TO>::type;
};

struct Foo {
  int& bar() { return barImpl(*this); }
  const int& bar() const { return barImpl(*this); }
private:
  template<typename THIS>
  static auto barImpl(THIS&& instance) -> typename CopyConst<THIS, int>::type& {
  	return instance.x;
  }
  int x = 5;
};

int main() {
	static_assert(is_same<int&, decltype(declval<Foo>().bar())>::value,
		"Non-const foo.bar() result must yield a non-const reference");
	static_assert(is_same<const int&, decltype(declval<const Foo>().bar())>::value,
		"Const foo.bar() result must yield a const reference");

	return 0;
}