On Thursday, 8 September 2016 at 08:20:49 UTC, Jon Degenhardt
wrote:
I've been generalizing output routines by passing an
OutputRange as an argument. This gets interesting when the
output routine is an virtual function. Virtual functions cannot
be templates, so instead the template parameters need to be
part of class definition and specified when instantiating the
class.
An example is below. It works fine. One thing I can't figure
out: how to provide the range parameter without first declaring
a variable of the appropriate type. What works is something
like:
auto writer = stdout.lockingTextWriter;
auto x = new Derived!(typeof(writer));
Other forms I've tried fail to compile. For example, this fails:
auto x = new Derived!(typeof(stdout.lockingTextWriter));
I'm curious if this can be done without declaring the variable
first. Anyone happen to know?
--Jon
Full example:
import std.stdio;
import std.range;
class Base(OutputRange)
{
abstract void writeString(OutputRange r, string s);
}
class Derived(OutputRange) : Base!OutputRange
{
override void writeString(OutputRange r, string s)
{
put(r, s);
put(r, '\n');
}
}
void main()
{
auto writer = stdout.lockingTextWriter;
auto x = new Derived!(typeof(writer));
x.writeString(writer, "Hello World");
}
I think that
auto x = new Derived!(typeof(stdout.lockingTextWriter()))(); //
note the parenthesis
should work.
But usually, you save the writer inside the object and make a
free function called `derived` (same as the class, but with
lowercase first). You define it this way:
auto derived(OutputRange)(auto ref OutputRange writer)
{
auto result = new Derived!OutputRange();
result.writer = writer; // save the writer in a field of the
object
return result;
}
void main()
{
auto x = derived(stdout.lockingTextWriter);
x.writeString("Hello world"); // the writer is saved in the
object, no need to pass it
}