Jump to page: 1 2
Thread overview
Iterate over symbols in tupleof without instance
Apr 15, 2014
Benjamin Thaut
Apr 15, 2014
Rikki Cattermole
Apr 15, 2014
Dicebot
Apr 15, 2014
Dicebot
Apr 15, 2014
Artur Skawina
Apr 15, 2014
Dicebot
Apr 15, 2014
Artur Skawina
Apr 15, 2014
Dicebot
Apr 15, 2014
Benjamin Thaut
Apr 15, 2014
Dicebot
Apr 15, 2014
Benjamin Thaut
Apr 15, 2014
monarch_dodra
April 15, 2014
I would like to iterate over T.tupleof at compiletime without having a instance of the given type. So fare the only way I found that works is the following

void iterateImpl(T, size_t i)()
{
  static if(i < T.tupleof.length)
  {
     // do something with T.tupleof[i]
     iterateImpl!(T, i+1)();
  }
}

void iterate(T)()
{
  iterateImpl!(T, 0)();
}

But this is quite ugly, as there will tons of stack frames on the stack during runtime. I really wanted something like:

void iterate(T)()
{

  foreach(size_t i, m; T.tupleof)
  // error message: "Need this to access <member name here>"
  {
     // do something with m
  }
}

Kind Regards
Benjamin Thaut

April 15, 2014
On Tuesday, 15 April 2014 at 08:18:31 UTC, Benjamin Thaut wrote:
> I would like to iterate over T.tupleof at compiletime without having a instance of the given type. So fare the only way I found that works is the following
>
> void iterateImpl(T, size_t i)()
> {
>   static if(i < T.tupleof.length)
>   {
>      // do something with T.tupleof[i]
>      iterateImpl!(T, i+1)();
>   }
> }
>
> void iterate(T)()
> {
>   iterateImpl!(T, 0)();
> }
>
> But this is quite ugly, as there will tons of stack frames on the stack during runtime. I really wanted something like:
>
> void iterate(T)()
> {
>
>   foreach(size_t i, m; T.tupleof)
>   // error message: "Need this to access <member name here>"
>   {
>      // do something with m
>   }
> }
>
> Kind Regards
> Benjamin Thaut

Kinda like this?

import std.stdio;
void test(T...)(T args) {
	if (!__ctfe)
		writeln(args);
	foreach(arg; T) {
		pragma(msg, arg);	
	}
}

void main() {
	test("a", "b", "c", 7, 2, 9);	
}

Compilation output:
string
string
string
int
int
int

Application output:
abc729
April 15, 2014
On Tuesday, 15 April 2014 at 08:18:31 UTC, Benjamin Thaut wrote:
> void iterate(T)()
> {
>
>   foreach(size_t i, m; T.tupleof)
>   // error message: "Need this to access <member name here>"
>   {
>      // do something with m
>   }
> }
>
> Kind Regards
> Benjamin Thaut

Is this acceptable?

void iterate(T)()
{
	foreach (index, member; T.init.tupleof)
	{
		pragma(msg, __traits(identifier, T.tupleof[index]));
	}
}

struct A
{
	int a, b, c;
}

void main()
{
	iterate!A();
}

Reason why you can't naively iterate over T.tupleof is that current tuple foreach tries to look like normal foreach and thus iteration parameters can't be  types. If http://wiki.dlang.org/DIP57 is ever to be implemented, this will be fixed.
April 15, 2014
T.init _is_ effectively an instance of given type here but it is present in application anyway so it shouldn't create any _extra_ instance.
April 15, 2014
On 04/15/14 12:45, Dicebot wrote:
> void iterate(T)()
> {
>     foreach (index, member; T.init.tupleof)
>     {
>         pragma(msg, __traits(identifier, T.tupleof[index]));
>     }
> }
> 
> struct A
> {
>     int a, b, c;
> }
> 
> void main()
> {
>     iterate!A();
> }
> 
> Reason why you can't naively iterate over T.tupleof is that current tuple foreach tries to look like normal foreach and thus iteration parameters can't be  types.

   void iterate(T)()
   {
       foreach (index, member; typeof(T.tupleof))
       {
           pragma(msg, __traits(identifier, T.tupleof[index]));
       }
   }

artur
April 15, 2014
On Tuesday, 15 April 2014 at 08:18:31 UTC, Benjamin Thaut wrote:
> I would like to iterate over T.tupleof at compiletime without having a instance of the given type.

*What* exactly are you trying to do? You could iterate over the tupleof *types* instead if you want? Would that work for you?

foreach(i, SubT; FieldTypeTuple!T)
{
    ...
}

You get your static loop, your indexes, and types. And if you need to operate on the subtypes, you can always use `SubT a = SubT.init;`

Also, as a general rule, it is "recommended" to not use tupleof directly, but rather:

T myData;
foreach(i, SubT; FieldTypeTuple!T)
{
    alias subData = myData.tupleof[i];
}

This is because FieldTypeTuple will strip the "context pointer field", which you generally don't care about.
April 15, 2014
On Tuesday, 15 April 2014 at 11:25:14 UTC, Artur Skawina wrote:
>    void iterate(T)()
>    {
>        foreach (index, member; typeof(T.tupleof))
>        {
>            pragma(msg, __traits(identifier, T.tupleof[index]));
>        }
>    }
>
> artur

So ashamed :D
April 15, 2014
On 04/15/14 13:33, Dicebot wrote:
> On Tuesday, 15 April 2014 at 11:25:14 UTC, Artur Skawina wrote:
>>    void iterate(T)()
>>    {
>>        foreach (index, member; typeof(T.tupleof))
>>        {
>>            pragma(msg, __traits(identifier, T.tupleof[index]));
>>        }
>>    }
> 
> So ashamed :D

I would have not thought of that either, if Jacob didn't mention it... :)

http://forum.dlang.org/post/jl9gil$i9l$1@digitalmars.com

artur
April 15, 2014
On Tuesday, 15 April 2014 at 12:11:52 UTC, Artur Skawina wrote:
> On 04/15/14 13:33, Dicebot wrote:
>> On Tuesday, 15 April 2014 at 11:25:14 UTC, Artur Skawina wrote:
>>>    void iterate(T)()
>>>    {
>>>        foreach (index, member; typeof(T.tupleof))
>>>        {
>>>            pragma(msg, __traits(identifier, T.tupleof[index]));
>>>        }
>>>    }
>> 
>> So ashamed :D
>
> I would have not thought of that either, if Jacob didn't mention it... :)
>
> http://forum.dlang.org/post/jl9gil$i9l$1@digitalmars.com
>
> artur

What I mean is that my initial statement is blatantly wrong - of course D does support iteration over arbitrary entities, because it does support iteration over  TypeTuple!(...). Must have been some sort of brainfart.

This trick does make some sense if you think about it. T.tupleof is a list of aggregate field symbols which are normally resolved as values. But you need a context pointer to work with aggregate fields so naive value iteration is not possible. This behavior is necessary to support idioms like this:

int a, b;
TypeTuple!(a, b)[] = TypeTuple!(42, 42)[];

Error message could have been better though.
April 15, 2014
Am 15.04.2014 13:25, schrieb Artur Skawina:
> On 04/15/14 12:45, Dicebot wrote:
>> void iterate(T)()
>> {
>>      foreach (index, member; T.init.tupleof)
>>      {
>>          pragma(msg, __traits(identifier, T.tupleof[index]));
>>      }
>> }
>>
>> struct A
>> {
>>      int a, b, c;
>> }
>>
>> void main()
>> {
>>      iterate!A();
>> }
>>
>> Reason why you can't naively iterate over T.tupleof is that current tuple foreach tries to look like normal foreach and thus iteration parameters can't be  types.
>
>     void iterate(T)()
>     {
>         foreach (index, member; typeof(T.tupleof))
>         {
>             pragma(msg, __traits(identifier, T.tupleof[index]));
>         }
>     }
>
> artur
>

I want to iterate over the symbols, not over the types that the symbols have. I need to iterate over the symbols, because UDAs are attached to the symbols. Because of that none of the here listed solutions work for me.

Here is a small example of what I'm trying to do: http://dpaste.dzfl.pl/4645d6537447

And no, I can not use __traits(allMembers, T) and __traits(getMember, T, m) because some time ago __traits(getMember, ...) was changed so it can no longer access protected members. (obviously it will work if the type that should be iterated over is within the same module, but thats not the case in practice.)

Kind Regards
Benjamin Thaut
« First   ‹ Prev
1 2