struct sfinae_one { char a[1]; };
struct sfinae_two { char a[2]; };
const char* get_value_description(int is_glvalue, int is_rvalue)
{
if (is_glvalue == sizeof (sfinae_one)) return "prvalue";
if (is_rvalue == sizeof (sfinae_one)) return "lvalue";
return "xvalue";
}
template<typename T>
sfinae_one SFINAE_test_1( const T& t );
template<typename T>
sfinae_two SFINAE_test_1( T& t );
template<typename T>
sfinae_one SFINAE_test_2( const T& t );
template<typename T>
sfinae_two SFINAE_test_2( T&& t );
#define VALUE_CAT(expr) get_value_description(sizeof SFINAE_test_1((expr)), sizeof SFINAE_test_2((expr)))
#include <iostream>
using namespace std;
int main()
{
int x;
cout << VALUE_CAT(x) << endl; // prints lvalue
cout << VALUE_CAT(move(x)) << endl; // prints xvalue
cout << VALUE_CAT(42) << endl; // prints prvalue
}
c3RydWN0IHNmaW5hZV9vbmUgeyBjaGFyIGFbMV07IH07CnN0cnVjdCBzZmluYWVfdHdvIHsgY2hhciBhWzJdOyB9OwoKY29uc3QgY2hhciogZ2V0X3ZhbHVlX2Rlc2NyaXB0aW9uKGludCBpc19nbHZhbHVlLCBpbnQgaXNfcnZhbHVlKQp7CiAgICBpZiAoaXNfZ2x2YWx1ZSA9PSBzaXplb2YgKHNmaW5hZV9vbmUpKSByZXR1cm4gInBydmFsdWUiOwogICAgaWYgKGlzX3J2YWx1ZSA9PSBzaXplb2YgKHNmaW5hZV9vbmUpKSByZXR1cm4gImx2YWx1ZSI7CiAgICByZXR1cm4gInh2YWx1ZSI7Cn0KCnRlbXBsYXRlPHR5cGVuYW1lIFQ+CnNmaW5hZV9vbmUgU0ZJTkFFX3Rlc3RfMSggY29uc3QgVCYgdCApOwp0ZW1wbGF0ZTx0eXBlbmFtZSBUPgpzZmluYWVfdHdvIFNGSU5BRV90ZXN0XzEoIFQmIHQgKTsKCnRlbXBsYXRlPHR5cGVuYW1lIFQ+CnNmaW5hZV9vbmUgU0ZJTkFFX3Rlc3RfMiggY29uc3QgVCYgdCApOwp0ZW1wbGF0ZTx0eXBlbmFtZSBUPgpzZmluYWVfdHdvIFNGSU5BRV90ZXN0XzIoIFQmJiB0ICk7CgojZGVmaW5lIFZBTFVFX0NBVChleHByKSBnZXRfdmFsdWVfZGVzY3JpcHRpb24oc2l6ZW9mIFNGSU5BRV90ZXN0XzEoKGV4cHIpKSwgc2l6ZW9mIFNGSU5BRV90ZXN0XzIoKGV4cHIpKSkKCiNpbmNsdWRlIDxpb3N0cmVhbT4KdXNpbmcgbmFtZXNwYWNlIHN0ZDsKaW50IG1haW4oKQp7CiAgICBpbnQgeDsKCiAgICBjb3V0IDw8IFZBTFVFX0NBVCh4KSA8PCBlbmRsOyAvLyBwcmludHMgbHZhbHVlCiAgICBjb3V0IDw8IFZBTFVFX0NBVChtb3ZlKHgpKSA8PCBlbmRsOyAvLyBwcmludHMgeHZhbHVlCiAgICBjb3V0IDw8IFZBTFVFX0NBVCg0MikgPDwgZW5kbDsgLy8gcHJpbnRzIHBydmFsdWUKfQ==