Re: Store struct tuple of alias and access members through it?

2018-04-19 Thread Timoses via Digitalmars-d-learn

On Saturday, 7 April 2018 at 19:21:30 UTC, Simen Kjærås wrote:

import std.meta;
import std.traits;

// List all member functions, and wrap them such that 
myFoo.fun(3) can be called as 
AllMemberFunctions!(typeof(myFoo))[idx](myFoo, 3).

template AllMemberFunctions(T)
{
template createDg(alias fn)
{
static if (__traits(isStaticFunction, fn))
alias createDg = fn;
else
ReturnType!fn createDg(ref T ctx, Parameters!fn 
args)

{
ReturnType!fn delegate(Parameters!fn) fun;
fun.funcptr = &fn;
fun.ptr = cast(void*)&ctx;
return fun(args);
}
}

alias GetOverloads(string name) = 
AliasSeq!(__traits(getOverloads, T, name));


alias AllMemberFunctions = staticMap!(createDg, 
staticMap!(GetOverloads, __traits(allMembers, T)));

}

--
  Simen


Many thanks for this!!! Was really helpful.

I ended up unfolding the struct members into an array of member 
strings and mapping those to either the struct tuple members or 
the struct function members.
This way I can call all members (normal and bitfield members) in 
order.


Result:
https://gist.github.com/Timoses/c78e599e91b8d05be34aefaf75ca3739


This project is really teaching me some template actions : D.


Re: Store struct tuple of alias and access members through it?

2018-04-07 Thread Alex via Digitalmars-d-learn

On Saturday, 7 April 2018 at 13:31:01 UTC, Timoses wrote:

Simen was faster :)

In my solution I simply ignore such things as functions... But 
there is the cool delegate creation approach in Simen's solution 
for this. I can handle arrays instead. :)

And I got rid of tupelof acting on an instance.

Be aware, that bitfields create more fields then the delegates 
for the bitfield's members...


import std.stdio;
import std.bitmanip;
import std.traits;

void main()
{
S s;
Param!S example = new Param!S(s);

writeln(example[0]);
writeln(example[1]);
writeln(example[2]);
writeln(example[3]);
writeln(example[4]);
writeln(example[5]);
writeln(example[6]);

writeln([__traits(allMembers, S)]);

writeln(example[15]);
writeln(example[16]);
writeln(example[17]);
writeln(example[18]);
}

struct S
{
uint s1;
ushort s2;

string s3;
float s4;

mixin(bitfields!(
uint, "x",2,
int,  "y",3,
uint, "z",2,
bool, "flag", 1));

size_t fun(){ return 42; }

size_t delegate() dg;

size_t[] arr;

static void fun(){}
}

interface IParam{}

class Param(T) : IParam
{
T m;
this(T m)
{
this.m = m;
}

IParam opIndex(size_t i)
{
//static if(!isBasicType!T)
static if(__traits(compiles, __traits(allMembers, T)))
{
static foreach (j, t; __traits(allMembers, T))
{
if (i == j)
{
		static if(__traits(compiles, new 
Param!(typeof(__traits(getMember, this.m, 
t)))(__traits(getMember, this.m, t

{
			return new Param!(typeof(__traits(getMember, 
this.m, t)))(__traits(getMember, this.m, t));

}
}
}
}
return null;
}
}


Re: Store struct tuple of alias and access members through it?

2018-04-07 Thread Simen Kjærås via Digitalmars-d-learn

On Saturday, 7 April 2018 at 13:31:01 UTC, Timoses wrote:

In the end I would like to accomplish the following:
Provide access to contained bitfields and members of a struct 
in the order they

appear in the struct via an index.


The behavior of Type.tupleof in D seems a bit unfinished - they 
can't be passed to other functions, they can't be directly used 
to get the member they refer to, and the indirect way is clunky.


Anyways. Your desired code `return this.m.members[i];` is, as you 
have noticed, impossible. There's multiple reasons for that - 
first, `members` can't be used like that. Second, since you need 
to wrap it in a Param instance, you need more information than 
that. Third, there's a clear distinction in D between 
compile-time and run-time values, so you need the static foreach 
there to get the right compile-time value.


Now, what *can* we do?

First, there's no need for __traits(getMember, this.m, 
members[j].stringof), since the index into T.tupleof is the exact 
same as for m.tupleof. In other words, you could use


return new Param!(typeof(m.tupleof[j]))(m.tupleof[j]);

I think that is clearer. I'd suggest also creating this function:

IParam param(T)(T value) {
return new Param!T(value);
}

That way, the above line would be

return param(m.tupleof[j]);

Handling methods is a tad more complicated, and you will not get 
the correct interleaving of methods and fields, which may or may 
not be a problem to you.


Here's my attempt at solving all your problems. There may be 
things I've misunderstood, forgotten or ignored, and there are 
certainly places where I'm unsure.



import std.meta;
import std.traits;

// List all member functions, and wrap them such that 
myFoo.fun(3) can be called as 
AllMemberFunctions!(typeof(myFoo))[idx](myFoo, 3).

template AllMemberFunctions(T)
{
template createDg(alias fn)
{
static if (__traits(isStaticFunction, fn))
alias createDg = fn;
else
ReturnType!fn createDg(ref T ctx, Parameters!fn args)
{
ReturnType!fn delegate(Parameters!fn) fun;
fun.funcptr = &fn;
fun.ptr = cast(void*)&ctx;
return fun(args);
}
}

alias GetOverloads(string name) = 
AliasSeq!(__traits(getOverloads, T, name));


alias AllMemberFunctions = staticMap!(createDg, 
staticMap!(GetOverloads, __traits(allMembers, T)));

}

interface IParam
{
// Moved this here, since otherwise you'd need to know the
// exact template parameters to Param to get to anything.
IParam opIndex(size_t i);
}


// Simplified template definition.
class Param(T) : IParam
{
T m;
this(T m)
{
this.m = m;
}

static if (!isBasicType!T && !isArray!T && 
!isFunctionPointer!T)

{
IParam opIndex(size_t i)
{
switch (i)
{
// Go through all members:
static foreach (j; 0..m.tupleof.length)
case j:
return param(m.tupleof[j]);
// Then all functions after:
static foreach (j, fn; AllMemberFunctions!T)
case j+m.tupleof.length:
return param(&fn);
// And blow up if the index is invalid.
default:
assert(false, "Invalid index!");
}
}
}
else
{
IParam opIndex(size_t i)
{
assert(false, T.stringof ~ " is not an aggregate 
type, and can't be indexed.");

}
}
}

IParam param(T)(T value) {
return new Param!T(value);
}

struct S {
int n;
float f;
string s;
int fn() { return n+2; }
string fun() { return ""; }
string fun(int n) { return ""; }
static void func() {}
}


unittest {
S s;
IParam a = param(s);
}

--
  Simen


Store struct tuple of alias and access members through it?

2018-04-07 Thread Timoses via Digitalmars-d-learn

(Please read at the very bottom what I'd like to achieve)

Is it possible to return the member of a struct by its .tupleof 
index?


I know that it would work on a struct value, but I'd like it to 
work on the type's tupleof:


```
struct S { int i;}
S s;
// below leads to: Error: need this for s1 of type uint
// writeln(/*somehow access s via the S tupleof? */ S.tupleof[0]);
// vs
writeln(s.tupleof[0]);
```

See below example to make the intention a bit clearer:

https://run.dlang.io/gist/6fdb01ddd78b14f8b9a94ac951580cb8
```
struct S
{
uint s1;
ushort s2;
}

interface IParam
{}

template Param(T)
{
static if (isBasicType!T)
alias members = AliasSeq!();
else
alias members = AliasSeq!(T.tupleof);

class Param : IParam
{
T m;
this(T m)
{
this.m = m;
}

IParam opIndex(size_t i)
{
// Something like this possible?
// return this.m.members[i];   // < 
how???


// This works but feels needless.
static foreach (j, t; members)
if (i == j)
{
	return new 
Param!(typeof(members[j]))(__traits(getMember, this.m, 
members[j].stringof));  // <- 
members[j].stringof feels ugly just to get the member that should 
be stored in 'members' already...

}
return null;
}
}
}
```

The reason why I don't want `m.tupleof[i]` is because later I'd 
like to consider bitfields within the struct. This means I'd have 
to also consider the member functions of the struct and 
potentially return them.


E.g.

```
struct S
{
int s1;
int s2() { return 3; }
}
```

and then I'd like to have
alias members = (s1, s2) // pseudo code..

so I could return
S s;
s.members[1]; // would evaluate the function s2 and return the 
value


--

In the end I would like to accomplish the following:
Provide access to contained bitfields and members of a struct in 
the order they

appear in the struct via an index.

I hope I made a somewhat decent job in explaining what I'm trying 
to accomplish.


Please let me know if anything is unclear.