How to expand an expression along with a parameter tuple?

Artur Skawina art.08.09 at gmail.com
Mon Jun 17 06:59:17 PDT 2013


On 06/17/13 14:57, TommiT wrote:
> On Monday, 17 June 2013 at 12:21:31 UTC, Artur Skawina wrote:
>>
>> A more correct, but a bit less readable version (the types of 'values' and 'arr'
>> elements do not have to match) would be:
>>
>>    void bar(T...)(T values) {
>>       static if (T.length) {
>>          NTup!(T.length, typeof(arr[T[0].init])) tmp;
>>          foreach (i, ref v; values)
>>             tmp[i] = arr[v]*10;
>>          foo(tmp);
>>       }
>>       else
>>          foo();
>>    }
>>
>>    template NTup(size_t N, T...) {
>>       static if (N>1)
>>          alias NTup = NTup!(N-1, T, T[$-1]);
>>       else
>>          alias NTup = T;
>>    }
> 
> Argh, that's a lot of boilerplate. Thanks for pointing this out. I didn't notice in your previous example that the expression types had to match with the parameter types. Now I really do think that we need the C++ ellipsis notation (it's just the ellipsis can be omitted when it would be right next to the tuple):
> 
> void bar(T...)(T values)
> {
>     foo((arr[values] * 10)...);
> }
> 

Well, the only real difference between these two examples is

   s/T tmp/NTup!(T.length, typeof(arr[T[0].init])) tmp/

'NTup' would be a lib thing, and the empty-args case would
have to handled (or disallowed) in real code anyway. So it's not
/that/ much more boilerplate.


Another solution would be to have the following hidden in some lib:

   struct _ForEach(alias MAP, TS...) {
      NTup!(TS.length, typeof(MAP(TS[0].init))) tuple;

      this(TS values) {
         foreach (i, ref v; values)
            tuple[i] = MAP(v);
      }
   }

   auto ForEach(alias MAP, TS...)(TS ts) {
      return _ForEach!(MAP, TS)(ts); 
   }
   
Then 'bar' becomes just:

   void bar(T...)(T values) {
      foo(ForEach!(a=>arr[a]*10)(values).tuple);
   }

Yes, this is not as concise as '...' would be. But, with a bit more
tuple support in the language, the '.tuple' part wouldn't be
necessary, and then it's just

      foo(ForEach!(a=>arr[a]*10)(values));
vs
      foo((arr[values] * 10)...);

artur


More information about the Digitalmars-d-learn mailing list