www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Unwrap variadic template into vararg of pointers of the same types

reply ryuukk_ <ryuukk.dev gmail.com> writes:
I'm not sure how to phrase it so it'll try with code

I have this piece of code that i would like to improve, right now 
i have to create bunch of duplicates

```D
     void view_it(A, B)(void function(entity_t, A*, B*) cb)
     {
         foreach(it, e; view!(Includes!(A, B)))
         {
             auto a = it.get!(A)(e);
             auto b = it.get!(B)(e);
             cb(e, a, b);
         }
     }
```

The problem when i try to introduce variadic template, is i can't 
seem to understand how to unwrap the parameter as pointer type T 
-> T*


```D
struct Includes(Args...) { alias args = Args; }

void view_it(Includes)(void function(entity_t, Includes.args* ) 
cb)
{
     // do stuff
}

```

I get the following:

```Error: cannot have pointer to `(EEntityRemoved)```

Anyone got an idea?

Thanks!
Jul 08 2022
next sibling parent reply wjoe <invalid example.com> writes:
On Friday, 8 July 2022 at 12:20:13 UTC, ryuukk_ wrote:
 I'm not sure how to phrase it so it'll try with code

 I have this piece of code that i would like to improve, right 
 now i have to create bunch of duplicates

 ```D
     void view_it(A, B)(void function(entity_t, A*, B*) cb)
     {
         foreach(it, e; view!(Includes!(A, B)))
         {
             auto a = it.get!(A)(e);
             auto b = it.get!(B)(e);
             cb(e, a, b);
         }
     }
 ```

 The problem when i try to introduce variadic template, is i 
 can't seem to understand how to unwrap the parameter as pointer 
 type T -> T*


 ```D
 struct Includes(Args...) { alias args = Args; }

 void view_it(Includes)(void function(entity_t, Includes.args* ) 
 cb)
 {
     // do stuff
 }

 ```

 I get the following:

 ```Error: cannot have pointer to `(EEntityRemoved)```

 Anyone got an idea?

 Thanks!
I suppose you could do something like this: ```d template Includes(Args...) { template Recurse(Arg...) { import std.meta: AliasSeq; static if (1 == Arg.length) alias Recurse = AliasSeq!(Arg[0]*); else alias Recurse = AliasSeq!(Arg[0]*, Recurse!(Arg[0..$]); } alias Includes = Includes!(Args); } void view_it(Args...)(void function(entity_t, Includes!(Args) ) ```
Jul 08 2022
parent wjoe <invalid example.com> writes:
Corrections:

On Friday, 8 July 2022 at 12:40:52 UTC, wjoe wrote:
         alias Recurse = AliasSeq!(Arg[0]*, Recurse!(Arg[0..$]);
```d alias Recurse = AliasSeq!(Arg[0]*, Recurse!(Arg[1..$]); ```
 void view_it(Args...)(void function(entity_t, Includes!(Args) )
```d void view_it(Args...)(void function(entity_t, Includes!(Args) cb)) {...} ```
Jul 08 2022
prev sibling parent reply Paul Backus <snarwin gmail.com> writes:
On Friday, 8 July 2022 at 12:20:13 UTC, ryuukk_ wrote:
 The problem when i try to introduce variadic template, is i 
 can't seem to understand how to unwrap the parameter as pointer 
 type T -> T*


 ```D
 struct Includes(Args...) { alias args = Args; }

 void view_it(Includes)(void function(entity_t, Includes.args* ) 
 cb)
 {
     // do stuff
 }

 ```

 I get the following:

 ```Error: cannot have pointer to `(EEntityRemoved)```
You can use [`std.meta.staticMap`][1] to make each type into a pointer individually: ```d import std.meta; alias Args = AliasSeq!(int, string, double); struct Includes { alias args = Args; } struct entity_t {} alias PointerTo(T) = T*; void view_it(void function(entity_t, staticMap!(PointerTo, Includes.args) ) cb) { // do stuff } ``` However, this will probably not work very well in your original code where `view_it` is a template, because the presence of `staticMap` in the parameter list will prevent the compiler from automatically deducing the template parameters. So, in this case, I think a better solution is to make the type of the callback fully generic, and use a template constraint to enforce your requirements: ```d import std.meta: allSatisfy; import std.traits: isPointer; void view_it(Callback)(Callback cb) if ( is(Callback == void function(entity_t, Args), Args...) && allSatisfy!(isPointer, Args) ) { // do stuff } ``` [1]: http://phobos.dpldocs.info/std.meta.staticMap.html
Jul 08 2022
parent ryuukk_ <ryuukk.dev gmail.com> writes:
On Friday, 8 July 2022 at 12:48:20 UTC, Paul Backus wrote:
 On Friday, 8 July 2022 at 12:20:13 UTC, ryuukk_ wrote:
 The problem when i try to introduce variadic template, is i 
 can't seem to understand how to unwrap the parameter as 
 pointer type T -> T*


 ```D
 struct Includes(Args...) { alias args = Args; }

 void view_it(Includes)(void function(entity_t, Includes.args* 
 ) cb)
 {
     // do stuff
 }

 ```

 I get the following:

 ```Error: cannot have pointer to `(EEntityRemoved)```
You can use [`std.meta.staticMap`][1] to make each type into a pointer individually: ```d import std.meta; alias Args = AliasSeq!(int, string, double); struct Includes { alias args = Args; } struct entity_t {} alias PointerTo(T) = T*; void view_it(void function(entity_t, staticMap!(PointerTo, Includes.args) ) cb) { // do stuff } ``` However, this will probably not work very well in your original code where `view_it` is a template, because the presence of `staticMap` in the parameter list will prevent the compiler from automatically deducing the template parameters. So, in this case, I think a better solution is to make the type of the callback fully generic, and use a template constraint to enforce your requirements: ```d import std.meta: allSatisfy; import std.traits: isPointer; void view_it(Callback)(Callback cb) if ( is(Callback == void function(entity_t, Args), Args...) && allSatisfy!(isPointer, Args) ) { // do stuff } ``` [1]: http://phobos.dpldocs.info/std.meta.staticMap.html
Looks like my previous message did not get sent, i might have pressed on the wrong button Thanks for the snippet, i ended up copying the code from the imports, since importing the modules tanks my compile speed Although i'd prefer not rely on generic callback since i want to keep code completion, so i'll have to dig a little more, but that's for later, the solution works for now
Jul 11 2022