#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 {
  template<typename T>
  auto bar(T&&) -> typename CopyConst<T, int>::type& {
  	static_assert(is_same<typename decay<T>::type, int>::value,
  		"Because probably the only reason this is templated now is for this behavior"
  		"and what you really wanted to say was 'give me an int please'");
  	return x;
  }
  int x = 5;
};

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

	return 0;
}