Template shenannigans with multiple datatypes

vit vit at vit.vit
Fri May 13 08:28:56 UTC 2022


On Friday, 13 May 2022 at 07:32:16 UTC, Chris Katko wrote:
> On Friday, 13 May 2022 at 07:05:36 UTC, vit wrote:
>> On Friday, 13 May 2022 at 06:43:39 UTC, Chris Katko wrote:
>>> I have an intrinsicGraph(T) class that is given a pointer to 
>>> a T dataSource and automatically polls that variable every 
>>> frame to add it to the graph, whether it's a float, double, 
>>> integer, and maybe bool.
>>>
>>> [...]
>>
>> I dont understand first qestion but second question has a 
>> solution:
>>
>> ```d
>> intrinsic_graph!T make_graph(T, Args...)(auto ref T val, auto 
>> ref Args args){
>> 	return new intrinsic_graph!T(val, args);
>> }
>>
>>
>> instrinsicGraph!float testGraph;
>> instrinsicGraph!ulong testGraph2;
>> // later
>> testGraph = make_graph(units[0].x, 100, 300, COLOR(1,0,0,1));
>> testGraph2 = make_graph(g.stats.fps, 100, 500, COLOR(1,0,0,1));
>>
>>
>> ```
>
> Okay, to clarify just in case I'm very confusing because I'm up 
> late.
>
> If I wanted a "multipleGraph". A graph that takes multiple 
> values and plots them on the same graph. I need to store a 
> buffer for each dataSource. Luckily, because I'm painting them 
> to the screen, the buffers only really need to be float even if 
> they started as a boolean, int, or double. However, if I'm 
> keeping a list of pointers to things I want to snoop when I 
> call onTick(), I can't think of a way to support multiple types:
>
> ```D
> class intrinsicGraph(T)
>    {
>    T* dataSource;
>    float[] buffer;
>
>    void onTick()
>      {
>      //grab datasource data and do something.
>      buffer ~= to!float(*datasource);
>      }
>    }
>
> auto g = intrinsicGraph!float(&myFloat);
> ```
>
> But what if there's multiple types?
>
> ```D
> class multiGraph(???)
>    {
>    ???[] dataSources;
>    float[] buffers;
>
>    void onTick()
>      {
>      //grab datasource data and do something.
>      foreach(d, i; dataSources)
>         buffers[i] ~= to!float(*d); //or whatever
>      }
>    }
>
> auto g = multiGraph!???(&myFloat, &myDouble, &myInteger);
>
> ```
>
> This is a kinda "dynamic language" feature but it feels like 
> this information is theoretically, knowable at static, 
> compile-time. I know what the variable types will be at 
> compile-time, but I don't know how to put them all in one class 
> and reference them automatically.

Try variadic templates:

```d
import std.meta : staticMap, allSatisfy;
import std.traits : PointerTarget, isPointer;
import std.conv : to;

alias Pointer(T) = T*;

     class MultiGraph(Ts...){
     	alias DataSources = staticMap!(Pointer, Ts);

        	DataSources dataSources;
        	float[][DataSources.length] buffers;

         this(DataSources dataSources){
         	this.dataSources = dataSources;
         }

         void onTick() {
             //grab datasource data and do something.
             foreach(enum i, ref d; dataSources)
                 buffers[i] ~= to!float(*d); //or whatever
         }
     }

     auto multiGraph(Ts...)(Ts ts)
     if(allSatisfy!(isPointer, Ts)){
     	return new MultiGraph!(staticMap!(PointerTarget, Ts))(ts);
     }


     void main(){
         float myFloat;
         double myDouble;
         int myInteger;
     	auto g = multiGraph(&myFloat, &myDouble, &myInteger);

}
```


More information about the Digitalmars-d-learn mailing list