Thread overview
Unwrap variadic template into vararg of pointers of the same types
Jul 08, 2022
ryuukk_
Jul 08, 2022
wjoe
Jul 08, 2022
wjoe
Jul 08, 2022
Paul Backus
Jul 11, 2022
ryuukk_
July 08, 2022

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

    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*

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!

July 08, 2022

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

    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*

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:

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) )
July 08, 2022

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*

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 to make each type into a pointer individually:

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:

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
}
July 08, 2022

Corrections:

On Friday, 8 July 2022 at 12:40:52 UTC, wjoe wrote:

>
    alias Recurse = AliasSeq!(Arg[0]*, Recurse!(Arg[0..$]);
         alias Recurse = AliasSeq!(Arg[0]*, Recurse!(Arg[1..$]);
>

void view_it(Args...)(void function(entity_t, Includes!(Args) )

void view_it(Args...)(void function(entity_t, Includes!(Args) cb)) {...}
July 11, 2022

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*

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 to make each type into a pointer individually:

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:

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
}

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