| Thread overview | |||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
March 30, 2009 Shouldn't __traits return Tuples? | ||||
|---|---|---|---|---|
| ||||
Shouldn't __traits return Tuples instead of arrays (esp. allMembers) to allow sophisticated compile time reflection?
Currently it seems impossible to do something along the lines of
foreach (member; __traits (allMembers, Class))
{
foreach (overload; __traits (getVirtualFunctions, Class, member))
{
// do stuff
}
}
Maybe it would be possible with Tuples using template recursion.
Also the following doesn't work with dmd, returns 0 for all members:
Base base = new Base;
auto members = __traits(allMembers, typeof(base));
foreach(m; members)
writefln(base.classinfo.getMembers(m).length);
| ||||
March 30, 2009 Re: Shouldn't __traits return Tuples? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Trass3r | On Mon, 30 Mar 2009 15:06:09 +0200, Trass3r <mrmocool@gmx.de> wrote: >Shouldn't __traits return Tuples instead of arrays (esp. allMembers) to >allow sophisticated compile time reflection? >Currently it seems impossible to do something along the lines of > >foreach (member; __traits (allMembers, Class)) >{ > foreach (overload; __traits (getVirtualFunctions, Class, member)) > { > // do stuff > } >} It's possible to statically unroll the foreach's with a template generating a tuple of consequtive integers (not tested): template Sequence(size_t count, size_t index = 0) { static if (index < count) alias Tuple!(index, Sequence!(count, index + 1)) Sequence; ... } enum members = __traits (allMembers, Class); foreach (i; Sequence!(members.length)) { enum funcs = __traits (getVirtualFunctions, Class, members[i]); foreach (j; Sequence!(funcs.length)) { // do stuff } } I'm not sure __traits should return tuples because arrays can be used with CTFE without generating an extra symbol, meaning less code bloat. > >Maybe it would be possible with Tuples using template recursion. > > > >Also the following doesn't work with dmd, returns 0 for all members: > >Base base = new Base; >auto members = __traits(allMembers, typeof(base)); >foreach(m; members) > writefln(base.classinfo.getMembers(m).length); getMembers has not been implemented, AFAIK | |||
March 30, 2009 Re: Shouldn't __traits return Tuples? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Max Samukha | On Mon, Mar 30, 2009 at 10:57 AM, Max Samukha <samukha@voliacable.com.removethis> wrote: >>Also the following doesn't work with dmd, returns 0 for all members: >> >>Base base = new Base; >>auto members = __traits(allMembers, typeof(base)); >>foreach(m; members) >> writefln(base.classinfo.getMembers(m).length); > > getMembers has not been implemented, AFAIK It has in LDC ;) | |||
March 30, 2009 Re: Shouldn't __traits return Tuples? | ||||
|---|---|---|---|---|
| ||||
On Mon, Mar 30, 2009 at 5:11 PM, Jarrett Billingsley <jarrett.billingsley@gmail.com> wrote: > On Mon, Mar 30, 2009 at 10:57 AM, Max Samukha <samukha@voliacable.com.removethis> wrote: >>>Also the following doesn't work with dmd, returns 0 for all members: >>> >>>Base base = new Base; >>>auto members = __traits(allMembers, typeof(base)); >>>foreach(m; members) >>> writefln(base.classinfo.getMembers(m).length); >> >> getMembers has not been implemented, AFAIK > > It has in LDC ;) > I think we need D2 support first ;) | ||||
March 30, 2009 Re: Shouldn't __traits return Tuples? | ||||
|---|---|---|---|---|
| ||||
On Mon, Mar 30, 2009 at 11:13 AM, Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> wrote:
>>> getMembers has not been implemented, AFAIK
>>
>> It has in LDC ;)
>>
>
> I think we need D2 support first ;)
I was talking about the RTTI getMembers function :)
| ||||
March 30, 2009 Re: Shouldn't __traits return Tuples? | ||||
|---|---|---|---|---|
| ||||
On Mon, Mar 30, 2009 at 5:13 PM, Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> wrote:
> On Mon, Mar 30, 2009 at 5:11 PM, Jarrett Billingsley <jarrett.billingsley@gmail.com> wrote:
>> On Mon, Mar 30, 2009 at 10:57 AM, Max Samukha <samukha@voliacable.com.removethis> wrote:
>>>>Also the following doesn't work with dmd, returns 0 for all members:
>>>>
>>>>Base base = new Base;
>>>>auto members = __traits(allMembers, typeof(base));
>>>>foreach(m; members)
>>>> writefln(base.classinfo.getMembers(m).length);
>>>
>>> getMembers has not been implemented, AFAIK
>>
>> It has in LDC ;)
>>
>
> I think we need D2 support first ;)
>
Maybe you're thinking of OffsetTypeInfo (classinfo.offTi) ? Yes that can be enabled when configuring LDC, before building the compiler.
| ||||
March 30, 2009 Re: Shouldn't __traits return Tuples? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Max Samukha | Max Samukha schrieb:
> It's possible to statically unroll the foreach's with a template
> generating a tuple of consequtive integers (not tested):
>
> template Sequence(size_t count, size_t index = 0)
> {
> static if (index < count)
> alias Tuple!(index, Sequence!(count, index + 1)) Sequence; ...
> }
>
> enum members = __traits (allMembers, Class);
> foreach (i; Sequence!(members.length))
> {
> enum funcs = __traits (getVirtualFunctions, Class, members[i]);
> foreach (j; Sequence!(funcs.length))
> {
> // do stuff
> }
> }
Well this is interesting. That code yields:
variable main.main._funcs_field_0 cannot be declared to be a function.
class Class
{
int foo(int i)
{
return 1;
}
}
[...]
auto funcs = __traits(getVirtualFunctions, Class, members[i])(1);
yields
Error: function expected before (), not tuple(foo) of type (int(int i))
So it is a tuple although the docs tell us it's an array?
Strangely this doesn't work either:
enum members = __traits (allMembers, Class);
foreach (i; Sequence!(members.length))
{
foreach (j; __traits(getVirtualFunctions, Class, members[i]))
{
writefln(typeid(typeof(j)));
// do stuff
}
}
Though it correctly gets foo() (leaving out typeof above yields "function main.Class.foo is used as a type") it doesn't compile when adding typeof:
"variable main.main.i voids have no value"
| |||
March 31, 2009 Re: Shouldn't __traits return Tuples? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Trass3r | On Mon, 30 Mar 2009 22:04:57 +0200, Trass3r <mrmocool@gmx.de> wrote: >Max Samukha schrieb: >> It's possible to statically unroll the foreach's with a template generating a tuple of consequtive integers (not tested): >> >> template Sequence(size_t count, size_t index = 0) >> { >> static if (index < count) >> alias Tuple!(index, Sequence!(count, index + 1)) Sequence; >> ... >> } >> >> enum members = __traits (allMembers, Class); >> foreach (i; Sequence!(members.length)) >> { >> enum funcs = __traits (getVirtualFunctions, Class, members[i]); >> foreach (j; Sequence!(funcs.length)) >> { >> // do stuff >> } >> } > >Well this is interesting. That code yields: >variable main.main._funcs_field_0 cannot be declared to be a function. > > >class Class >{ > int foo(int i) > { > return 1; > } >} >[...] > >auto funcs = __traits(getVirtualFunctions, Class, members[i])(1); > >yields >Error: function expected before (), not tuple(foo) of type (int(int i)) > >So it is a tuple although the docs tell us it's an array? > Yeah, __traits returns expressions of various types depending on the Id. In case of getVirtualFunctions, it's a tuple expression. You may want to look through traits.c in dmd sources to see what's going on. > >Strangely this doesn't work either: > >enum members = __traits (allMembers, Class); >foreach (i; Sequence!(members.length)) >{ > > foreach (j; __traits(getVirtualFunctions, Class, members[i])) > { > writefln(typeid(typeof(j))); > // do stuff > } >} > >Though it correctly gets foo() (leaving out typeof above yields "function main.Class.foo is used as a type") it doesn't compile when adding typeof: > >"variable main.main.i voids have no value" __traits is buggy. You could try to do what you want like this: template isFunction(C, string member) { enum isFunction = is(typeof(mixin("C." ~ member)) == function); } void main() { //SpinLock lock; enum members = __traits(allMembers, Class); foreach (i; Sequence!(members.length)) { static if (isFunction!(Class, members[i])) { foreach (j; __traits(getVirtualFunctions, Class, members[i])) writefln(members[i], ": ", typeid(typeof(j))); } } } | |||
March 31, 2009 Re: Shouldn't __traits return Tuples? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Max Samukha | On Tue, 31 Mar 2009 10:55:22 +0200, Max Samukha <samukha@voliacable.com.removethis> wrote: >On Mon, 30 Mar 2009 22:04:57 +0200, Trass3r <mrmocool@gmx.de> wrote: > >>Max Samukha schrieb: >>> It's possible to statically unroll the foreach's with a template generating a tuple of consequtive integers (not tested): >>> >>> template Sequence(size_t count, size_t index = 0) >>> { >>> static if (index < count) >>> alias Tuple!(index, Sequence!(count, index + 1)) Sequence; >>> ... >>> } >>> >>> enum members = __traits (allMembers, Class); >>> foreach (i; Sequence!(members.length)) >>> { >>> enum funcs = __traits (getVirtualFunctions, Class, members[i]); >>> foreach (j; Sequence!(funcs.length)) >>> { >>> // do stuff >>> } >>> } >> >>Well this is interesting. That code yields: >>variable main.main._funcs_field_0 cannot be declared to be a function. >> >> >>class Class >>{ >> int foo(int i) >> { >> return 1; >> } >>} >>[...] >> >>auto funcs = __traits(getVirtualFunctions, Class, members[i])(1); >> >>yields >>Error: function expected before (), not tuple(foo) of type (int(int i)) >> >>So it is a tuple although the docs tell us it's an array? >> > >Yeah, __traits returns expressions of various types depending on the Id. In case of getVirtualFunctions, it's a tuple expression. You may want to look through traits.c in dmd sources to see what's going on. > >> >>Strangely this doesn't work either: >> >>enum members = __traits (allMembers, Class); >>foreach (i; Sequence!(members.length)) >>{ >> >> foreach (j; __traits(getVirtualFunctions, Class, members[i])) >> { >> writefln(typeid(typeof(j))); >> // do stuff >> } >>} >> >>Though it correctly gets foo() (leaving out typeof above yields "function main.Class.foo is used as a type") it doesn't compile when adding typeof: >> >>"variable main.main.i voids have no value" > >__traits is buggy. You could try to do what you want like this: > >template isFunction(C, string member) >{ > enum isFunction = is(typeof(mixin("C." ~ member)) == function); >} > >void main() >{ > //SpinLock lock; > > enum members = __traits(allMembers, Class); > foreach (i; Sequence!(members.length)) > { > static if (isFunction!(Class, members[i])) > { > foreach (j; __traits(getVirtualFunctions, Class, >members[i])) > writefln(members[i], ": ", typeid(typeof(j))); > } > } >} SpinLock, you are out of place here. | |||
March 31, 2009 Re: Shouldn't __traits return Tuples? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Max Samukha | Max Samukha schrieb:
>> So it is a tuple although the docs tell us it's an array?
>>
>
> Yeah, __traits returns expressions of various types depending on the
> Id. In case of getVirtualFunctions, it's a tuple expression. You may
> want to look through traits.c in dmd sources to see what's going on.
>
So the docs are incorrect:
"getVirtualFunctions
The result is an array of the virtual overloads of that function."
| |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply