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

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

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

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

struct Foo {
  auto bar() -> typename CopyConst<decltype(*this), int>::type& {
  	return 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");
	const Foo foo;
	foo.bar();

	return 0;
}