## digitalmars.D.learn - how do I tell if something is lvalue?

Steven Schveighoffer <schveiguy yahoo.com> writes:
```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
```
Jan 31
Meta <jared771 gmail.com> writes:
```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)));
}
```
Jan 31
Steven Schveighoffer <schveiguy yahoo.com> writes:
```On 1/31/16 4:48 PM, Meta wrote:

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.

Thanks! I was surprised this is not straightforward.

-Steve
```
Jan 31
Meta <jared771 gmail.com> writes:
```On Sunday, 31 January 2016 at 22:11:45 UTC, Steven Schveighoffer
wrote:
On 1/31/16 4:48 PM, Meta wrote:

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.

Thanks! I was surprised this is not straightforward.

-Steve

It seems to me like it would be a useful addition to __traits.
```
Jan 31
Steven Schveighoffer <schveiguy yahoo.com> writes:
```On 1/31/16 5:12 PM, Meta wrote:
On Sunday, 31 January 2016 at 22:11:45 UTC, Steven Schveighoffer wrote:
On 1/31/16 4:48 PM, Meta wrote:

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.

Thanks! I was surprised this is not straightforward.

It seems to me like it would be a useful addition to __traits.

Yeah, the compiler probably has this handy.

https://issues.dlang.org/show_bug.cgi?id=15634

-Steve
```
Feb 01
Artur Skawina via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
```On 01/31/16 23:11, Steven Schveighoffer via Digitalmars-d-learn wrote:
Thanks! I was surprised this is not straightforward.

enum isLvalue(alias A) = is(typeof((ref _){}(A)));

artur
```
Feb 01
Meta <jared771 gmail.com> writes:
```On Monday, 1 February 2016 at 18:28:05 UTC, Artur Skawina wrote:
On 01/31/16 23:11, Steven Schveighoffer via Digitalmars-d-learn
wrote:
Thanks! I was surprised this is not straightforward.

enum isLvalue(alias A) = is(typeof((ref _){}(A)));

artur

That looks much nicer. It still needs work to properly handle
functions with non-empty argument lists. Also, can alias
parameters take runtime variables? I can't remember.

struct S
{
int w(int n) { return 1; }
}

static assert(isLvalue!(S.w));
```
Feb 01
Steven Schveighoffer <schveiguy yahoo.com> writes:
```On 2/1/16 2:47 PM, Meta wrote:
On Monday, 1 February 2016 at 18:28:05 UTC, Artur Skawina wrote:
On 01/31/16 23:11, Steven Schveighoffer via Digitalmars-d-learn wrote:
Thanks! I was surprised this is not straightforward.

enum isLvalue(alias A) = is(typeof((ref _){}(A)));

artur

That looks much nicer. It still needs work to properly handle functions
with non-empty argument lists. Also, can alias parameters take runtime
variables? I can't remember.

struct S
{
int w(int n) { return 1; }
}

static assert(isLvalue!(S.w));

Nice for the general case, but in my case, I don't need to worry about
parameters.

Thanks!

-Steve
```
Feb 01
Artur Skawina via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
```On 02/01/16 20:47, Meta via Digitalmars-d-learn wrote:
On Monday, 1 February 2016 at 18:28:05 UTC, Artur Skawina wrote:
On 01/31/16 23:11, Steven Schveighoffer via Digitalmars-d-learn wrote:
Thanks! I was surprised this is not straightforward.

enum isLvalue(alias A) = is(typeof((ref _){}(A)));

That looks much nicer. It still needs work to properly handle functions with
non-empty argument lists.

Then it gets a bit long for a one-liner ;)

enum isLvalue(A...) = is(typeof((ref _){}(A[0](A[1..\$])))) || is(typeof((ref
_){}(A[0])));

Also, can alias parameters take runtime variables? I can't remember.

Yes.

struct S
{
int w(int n) { return 1; }

ref int wl(int n) { return x; }
}

static assert(isLvalue!(S.w));

static assert(!isLvalue!(S.w, 1));
static assert(isLvalue!(S.wl, 1));

artur
```
Feb 01
Artur Skawina via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
```On 02/01/16 21:42, Artur Skawina wrote:
On 02/01/16 20:47, Meta via Digitalmars-d-learn wrote:
That looks much nicer. It still needs work to properly handle functions with
non-empty argument lists.

Then it gets a bit long for a one-liner ;)

enum isLvalue(A...) = is(typeof((ref _){}(A[0](A[1..\$])))) ||
is(typeof((ref _){}(A[0])));

And it's of course wrong in case there is a zero-args ref-returning

enum isLvalue(A...) = A.length>1?is(typeof((ref
_){}(A[0](A[1..\$])))):is(typeof((ref _){}(A[0])));

artur
```
Feb 01
Meta <jared771 gmail.com> writes:
```On Monday, 1 February 2016 at 20:53:35 UTC, Artur Skawina wrote:
On 02/01/16 21:42, Artur Skawina wrote:
On 02/01/16 20:47, Meta via Digitalmars-d-learn wrote:
That looks much nicer. It still needs work to properly handle
functions with non-empty argument lists.

Then it gets a bit long for a one-liner ;)

enum isLvalue(A...) = is(typeof((ref _){}(A[0](A[1..\$]))))
|| is(typeof((ref _){}(A[0])));

And it's of course wrong in case there is a zero-args

enum isLvalue(A...) = A.length>1?is(typeof((ref
_){}(A[0](A[1..\$])))):is(typeof((ref _){}(A[0])));

artur

Hmm, I think it can be simplified by replacing `A[0](A[1..\$])`
with `A(Parameters!A.init)`. Then the whole thing becomes:

enum isLvalue(alias A) = is(typeof((ref _) {}
(A(Parameters!A.init))));

*However*, we then run into this problem:

int n;

ref int returnN(int, float, bool) { return n; }
ref int returnN() { return n; }

static assert(isLvalue!returnN);

If I remember correctly this will just check the first returnN
declaration.
```
Feb 01
tsbockman <thomas.bockman gmail.com> writes:
```On Sunday, 31 January 2016 at 22:11:45 UTC, Steven Schveighoffer
wrote:
Thanks! I was surprised this is not straightforward.

-Steve

For function return values, at least, you can do this:

import std.traits, std.stdio;

int foo()
{
return 0;
}

ref int bar()
{
static int x = 0;
return x;
}

enum isRetByRef(alias func) = (functionAttributes!func &
FunctionAttribute.ref_) != 0;

void main()
{
writeln("foo: ", isRetByRef!foo);
writeln("bar: ", isRetByRef!bar);
}

(DPaste: http://dpaste.dzfl.pl/2aa8d3553a12)
```
Feb 01
Steven Schveighoffer <schveiguy yahoo.com> writes:
```On 2/1/16 5:20 PM, tsbockman wrote:
On Sunday, 31 January 2016 at 22:11:45 UTC, Steven Schveighoffer wrote:
Thanks! I was surprised this is not straightforward.

-Steve

For function return values, at least, you can do this:

import std.traits, std.stdio;

int foo()
{
return 0;
}

ref int bar()
{
static int x = 0;
return x;
}

enum isRetByRef(alias func) = (functionAttributes!func &
FunctionAttribute.ref_) != 0;

void main()
{
writeln("foo: ", isRetByRef!foo);
writeln("bar: ", isRetByRef!bar);
}

(DPaste: http://dpaste.dzfl.pl/2aa8d3553a12)

Thanks. In my case, I need to treat fields and properties that return by
ref the same way.

What I wanted essentially was a template constraint that says "this type
has a member named foo, and t.foo is an lvalue"

-Steve
```
Feb 01
tsbockman <thomas.bockman gmail.com> writes:
```On Monday, 1 February 2016 at 22:32:26 UTC, Steven Schveighoffer
wrote:
What I wanted essentially was a template constraint that says
"this type has a member named foo, and t.foo is an lvalue"

-Steve

Like this?

template hasLValProperty(T, string property) {
enum hasLValProperty = __traits(compiles, function(ref T x) {
void requireLVal(V)(ref V y) { }
requireLVal(mixin("x." ~ property));
});
}

struct Foo {
int a;
}
struct Bar {
int b() {
return 0; }
}
struct Baz {
ref int c() {
static int _c;
return _c;
}
}

void test(T, string property)() {
import std.stdio;
write(T.stringof, ".", property, " is ");
if(!hasLValProperty!(T, property))
write("NOT ");
writeln("an lvalue");
}

void main() {
import std.stdio;

test!(Foo, "a")();
test!(Foo, "b")();
test!(Bar, "a")();
test!(Bar, "b")();
test!(Baz, "c")();
}

(DPaste: http://dpaste.dzfl.pl/5877cc17ffd2)
```
Feb 01
=?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
```On 01/31/2016 01:48 PM, Meta wrote:

This seems to do the trick, although I haven't extensively tested it.

There is hasLvalueElements() as well. Its implementation my be similar
or give other ideas:

https://dlang.org/phobos/std_range_primitives.html#hasLvalueElements

Ali
```
Jan 31
Meta <jared771 gmail.com> writes:
```On Monday, 1 February 2016 at 00:20:00 UTC, Ali Ã‡ehreli wrote:
On 01/31/2016 01:48 PM, Meta wrote:

This seems to do the trick, although I haven't extensively
tested it.

There is hasLvalueElements() as well. Its implementation my be
similar or give other ideas:

https://dlang.org/phobos/std_range_primitives.html#hasLvalueElements

Ali

Unfortunately it's almost exactly the same as what I did, except
for front, back, etc. Looks like there is currently no easier way.
```
Jan 31