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)));
}

Reply via email to