February 01, 2016 Re: how do I tell if something is lvalue? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Meta | 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 |
February 01, 2016 Re: how do I tell if something is lvalue? | ||||
---|---|---|---|---|
| ||||
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 overload present. So... enum isLvalue(A...) = A.length>1?is(typeof((ref _){}(A[0](A[1..$])))):is(typeof((ref _){}(A[0]))); artur |
February 01, 2016 Re: how do I tell if something is lvalue? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Artur Skawina | 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 ref-returning overload present. So...
>
> 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.
|
February 01, 2016 Re: how do I tell if something is lvalue? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | 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) |
February 01, 2016 Re: how do I tell if something is lvalue? | ||||
---|---|---|---|---|
| ||||
Posted in reply to tsbockman | 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
|
February 02, 2016 Re: how do I tell if something is lvalue? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | 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) |
Copyright © 1999-2021 by the D Language Foundation