#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;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHlwZV90cmFpdHM+CnVzaW5nIG5hbWVzcGFjZSBzdGQ7Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBGUk9NLCB0eXBlbmFtZSBUTz4Kc3RydWN0IENvcHlDb25zdEltcGwgewoJdXNpbmcgdHlwZSA9IHR5cGVuYW1lIHN0ZDo6cmVtb3ZlX2NvbnN0PFRPPjo6dHlwZTsKfTsKCnRlbXBsYXRlPHR5cGVuYW1lIEZST00sIHR5cGVuYW1lIFRPPgpzdHJ1Y3QgQ29weUNvbnN0SW1wbDxjb25zdCBGUk9NLCBUTz4gewoJdXNpbmcgdHlwZSA9IHR5cGVuYW1lIHN0ZDo6YWRkX2NvbnN0PFRPPjo6dHlwZTsKfTsKCnRlbXBsYXRlPHR5cGVuYW1lIEZST00sIHR5cGVuYW1lIFRPPgpzdHJ1Y3QgQ29weUNvbnN0IHsKCXVzaW5nIHR5cGUgPSB0eXBlbmFtZSBDb3B5Q29uc3RJbXBsPHR5cGVuYW1lIHN0ZDo6cmVtb3ZlX3JlZmVyZW5jZTxGUk9NPjo6dHlwZSwgVE8+Ojp0eXBlOwp9OwoKc3RydWN0IEZvbyB7CiAgdGVtcGxhdGU8dHlwZW5hbWUgVD4KICBhdXRvIGJhcihUJiYpIC0+IHR5cGVuYW1lIENvcHlDb25zdDxULCBpbnQ+Ojp0eXBlJiB7CiAgCXN0YXRpY19hc3NlcnQoaXNfc2FtZTx0eXBlbmFtZSBkZWNheTxUPjo6dHlwZSwgaW50Pjo6dmFsdWUsCiAgCQkiQmVjYXVzZSBwcm9iYWJseSB0aGUgb25seSByZWFzb24gdGhpcyBpcyB0ZW1wbGF0ZWQgbm93IGlzIGZvciB0aGlzIGJlaGF2aW9yIgogIAkJImFuZCB3aGF0IHlvdSByZWFsbHkgd2FudGVkIHRvIHNheSB3YXMgJ2dpdmUgbWUgYW4gaW50IHBsZWFzZSciKTsKICAJcmV0dXJuIHg7CiAgfQogIGludCB4ID0gNTsKfTsKCmludCBtYWluKCkgewoJc3RhdGljX2Fzc2VydChpc19zYW1lPGludCYsIGRlY2x0eXBlKGRlY2x2YWw8Rm9vPigpLmJhcihkZWNsdmFsPGludD4oKSkpPjo6dmFsdWUsCgkJIk5vbi1jb25zdCBhcmcgdG8gZm9vLmJhcigpIHJlc3VsdCBtdXN0IGxlYWQgdG8gbm9uLWNvbnN0IHJlZmVyZW5jZSByZXN1bHQiKTsKCXN0YXRpY19hc3NlcnQoaXNfc2FtZTxjb25zdCBpbnQmLCBkZWNsdHlwZShkZWNsdmFsPEZvbz4oKS5iYXIoZGVjbHZhbDxjb25zdCBpbnQ+KCkpKT46OnZhbHVlLAoJCSJDb25zdCBhcmcgdG8gZm9vLmJhcigpIHJlc3VsdCBtdXN0IGxlYWQgdG8gY29uc3QgcmVmZXJlbmNlIHJlc3VsdCIpOwoKCXJldHVybiAwOwp9