how do I tell if something is lvalue?

Meta via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sun Jan 31 13:48:40 PST 2016


On Sunday, 31 January 2016 at 20:49:43 UTC, Steven Schveighoffer 
wrote:
> struct S
> {
>   int x;
>   ref int y() { return x; }
>   int z() { return 1; }
> }
>
> What can I use, given S, to determine that x and y yield 
> lvalues, while z yields an rvalue?
>
> I was expecting something like isLvalue somewhere, but cannot 
> find it.
>
> __traits(isRef, ...) doesn't work.
>
> -Steve

This seems to do the trick, although I haven't extensively tested 
it. There's probably a simpler way but this is the first thing I 
could come up with that works.

template yieldsLval(Aggregate, alias member)
{
	import std.traits: ReturnType;
	import std.functional: FunctionTypeOf;
	import std.typetuple: staticIndexOf;
	
	static if (isSomeFunction!member)
	{
		enum yieldsLval = __traits(compiles,
		{
			alias Ftype = FunctionTypeOf!member;
			void takesLval(ref ReturnType!Ftype) {}
			takesLval(Ftype());
		});
	}
	//It's a member variable
	else static if (staticIndexOf!(member.stringof, 
FieldNameTuple!Aggregate) > -1)
		enum yieldsLval = true;
	else
		static assert(false, "Symbol " ~ member.stringof ~ " is not a 
member function or variable of " ~ Aggregate.stringof);
}

struct S
{
	int x;
	ref int y() { return x; }
	int z() { return 1; }
	enum f = 0;
}

void main()
{
	static assert(yieldsLval!(S, S.y));
	static assert(yieldsLval!(S, S.x));
	static assert(!yieldsLval!(S, S.z));
	static assert(!__traits(compiles, yieldsLval!(S, S.f)));
}


More information about the Digitalmars-d-learn mailing list