www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Iterate over symbols in tupleof without instance

reply Benjamin Thaut <code benjamin-thaut.de> writes:
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
Apr 15 2014
next sibling parent "Rikki Cattermole" <alphaglosined gmail.com> writes:
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
Apr 15 2014
prev sibling next sibling parent reply "Dicebot" <public dicebot.lv> writes:
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.
Apr 15 2014
next sibling parent "Dicebot" <public dicebot.lv> writes:
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.
Apr 15 2014
prev sibling parent reply Artur Skawina <art.08.09 gmail.com> writes:
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
Apr 15 2014
next sibling parent reply "Dicebot" <public dicebot.lv> writes:
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
Apr 15 2014
parent reply Artur Skawina <art.08.09 gmail.com> writes:
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
Apr 15 2014
parent "Dicebot" <public dicebot.lv> writes:
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.
Apr 15 2014
prev sibling parent reply Benjamin Thaut <code benjamin-thaut.de> writes:
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
Apr 15 2014
parent reply "Dicebot" <public dicebot.lv> writes:
On Tuesday, 15 April 2014 at 12:30:44 UTC, Benjamin Thaut wrote:
 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
So, what is wrong with this? void main(string[] args) { Bla bla; foreach(index, a; typeof(Bla.tupleof)) { pragma(msg, hasAttribute!(Bla.tupleof[index], Property).stringof); } } http://dpaste.dzfl.pl/b38035362b29
Apr 15 2014
parent Benjamin Thaut <code benjamin-thaut.de> writes:
Am 15.04.2014 14:33, schrieb Dicebot:
 So, what is wrong with this?

 void main(string[] args)
 {
    Bla bla;
    foreach(index, a; typeof(Bla.tupleof))
    {
      pragma(msg, hasAttribute!(Bla.tupleof[index], Property).stringof);
    }
 }

 http://dpaste.dzfl.pl/b38035362b29
Nothing, thanks for the solution. It didn't come to my mind, to use the index from iterating over the type tuple to index the symbol tuple. Kind Regards Benjamin Thaut
Apr 15 2014
prev sibling parent "monarch_dodra" <monarchdodra gmail.com> writes:
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.
Apr 15 2014