1
votes

I'm making an input range to iterate over a custom container that holds data points that need to remain accurately paired as inputs and targets. I need different Ranges for returning training data (double[][]), inputs (double[]) and the targets (also double[]). I managed to get the following code to compile and work perfectly, but I don't know why.

public struct DataRange(string type) 
if( type == "TrainingData" || 
type == "InputData"    ||
type == "TargetData" )
{

  private immutable(int) length;
  private uint next;
  private Data data;

  this(Data d){
    this.length = d.numPoints;
    this.next = 0;
    this.data = d;
  }

  @property bool empty(){return next == length;}

  @property auto front(){
    static if(type == "TrainingData")
      return this.data.getTrainingData(next);
    else static if(type == "InputData")
      return this.data.getInputData(next);
    else return this.data.getTargetData(next);
  }

   void popFront(){++next;}
}
static assert(isInputRange!(DataRange!"TrainingData"));
static assert(isInputRange!(DataRange!"InputData"));
static assert(isInputRange!(DataRange!"TargetData"));

I've been reading the "The D Programming Language" by Alexandrescu, and I have found parameterized structs of the form

struct S(T){...} // or
struct S(T[]){...}

but these take type parameters, not expressions like I've done. I haven't been able to find any similar examples on dlang.org with parameterized types.

This compiles and works on DMD 2.066 and GDC 4.9.0.

I don't even know why I tried this, and looking back at it I don't know why it works. Anybody know what I'm missing? Where is this documented?

2
There is a useful book/tutorial on templates in D available online: github.com/PhilippeSigaud/D-templates-tutorial. It can explain things better than the language documentation sometimes. - yaz

2 Answers

2
votes

Ok, I found the answer. Though this wasn't specifically mentioned or described in any of the tutorials or anywhere in the book, I was eventually able to find it at http://dlang.org.template.html. Basically there are two things going on here.

1.) Though my code says struct, this is really a template (that results in a struct). I have seen examples of this online and in the book, though it wasn't described as a template. It was a bit confusing because I didn't use the template keyword, and in the book they are described as "parameterized."

2.) From the website linked above...

Template parameters can be types, values, symbols, or tuples

So in my case my template parameter was a symbol. The examples in the book used types.

Digging into the language specifications on the website reveals there is a lot more going on than is covered in the book!

1
votes

Alternatively you could use an enum to simplify the constraint in such a way that a wrong template instantiation is impossible (even if in your code the template constraint does it perfectly). example:

enum rangeKind{training, input, target};
public struct DataRange(rangeKind Kind)
{
}

void main(string args[])
{
    DataRange!(rangeKind.training) dr;
}