In C++03, Boost\'s Foreach, using this interesting technique, can detect at run-time whether an expression is an lvalue or an rvalue. (I found that via this StackOv
It took some effort, but here's a tested and working is_lvalue
macro that correctly handles const struct S
function return types. It relies on const struct S
rvalues not binding to const volatile struct S&
, while const struct S
lvalues do.
#include
template
struct nondeducible
{
typedef T type;
};
char (& is_lvalue_helper(...))[1];
template
char (& is_lvalue_helper(T&, typename nondeducible::type))[2];
#define is_lvalue(x) (sizeof(is_lvalue_helper((x),(x))) == 2)
struct S
{
int i;
};
template
void test_()
{
T a = {0};
T& b = a;
T (* c)() = 0;
T& (* d)() = 0;
assert (is_lvalue(a));
assert (is_lvalue(b));
assert (!is_lvalue(c()));
assert (is_lvalue(d()));
}
template
void test()
{
test_();
test_();
test_();
test_();
}
int main()
{
test();
test();
}
Edit: unnecessary extra parameter removed, thanks Xeo.
Edit again: As per the comments, this works with GCC but relies on unspecified behaviour in C++03 (it's valid C++11) and fails some other compilers. Extra parameter restored, which makes it work in more cases. const class rvalues give a hard error on some compilers, and give the correct result (false) on others.