February 01, 2016
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
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
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
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
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
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)
1 2
Next ›   Last »