Template shenannigans with multiple datatypes

Ali Çehreli acehreli at yahoo.com
Fri May 13 20:43:03 UTC 2022


On 5/13/22 00:32, Chris Katko wrote:

 > 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:

I think this is a classic example of OOP. You abstract data collection 
to classes that know how to deal with their own data type. The comments 
should explain it:

import std.algorithm;
import std.conv;
import std.range;
import std.random;
import std.stdio;

interface DataSource {
   // Represents "reporting" of data points to the graph.
   float[] dataPoints();

   // Represents a collection of data.
   void collect();
}

// A templatized implementation of DataSource that would
// work with fundamental types like 'int'.
class SimpleDataSource(T) : DataSource {
   T[] data;    // All collected data
   size_t next; // The beginning of data for next dataPoints()

   // Converts data to float[], the uniform representation.
   float[] dataPoints() {
     auto result = data[next..$].map!(to!float).array;
     next = data.length;
     return result;
   }

   void collect() {
     // Random number of random values
     const n = uniform(3, 10);
     iota(n).each!(i => data ~= uniform(10, 20));
   }
}

// Converted to a 'struct'. Could stay 'class'.
struct intrinsicGraph {
   DataSource[] dataSources;  // Same type collectors
   float[] buffer;            // Same type data

   void onTick() {
     // Go through all sources to update 'buffer'.
     dataSources.each!(source => buffer ~= source.dataPoints());
   }
}

void main() {
   // Independent collectors.
   auto source1 = new SimpleDataSource!int();
   auto source2 = new SimpleDataSource!double();

   auto g = intrinsicGraph();

   // This part is the "registration" of data sources,
   // which could be like g.register(source1).
   g.dataSources ~= source1;
   g.dataSources ~= source2;

   // Represents a time slice.
   foreach (i; 0 .. 3) {
     source1.collect();
     source2.collect();
     g.onTick();
   }

   // It works! :)
   writeln(g.buffer);
}

Ali



More information about the Digitalmars-d-learn mailing list