Using runtime polymorphic (class) ranges

The std.range module also provides interfaces for many of the range types. These are slower than using ranges with structs and templates directly, but have the advantage of using a single type for any object that matches the interface, This means that you can swap out the range implementation at runtime. It also has the advantage of providing a common application binary interface for cases such as class interfaces and building DLLs.

How to do it…

Let's make use of runtime polymorphic ranges by executing the following steps:

  1. Use the inputRangeObject or outputRangeObject functions, passing an instance of any range to them.
  2. Store and use the returned object by using the InputRange!type or OutputRange!type interfaces. The type there is the type returned by front.
  3. You can pass it to a function by using the element type and the interface, or cast it to a more specific range type (for example, cast(RandomAccessRange)) if more capabilities are needed.
  4. Remember to check for null whenever casting class objects.

The code is as follows:

import std.range;
InputRange!int myRange = inputRangeObject([1, 2, 3]);
foreach(int item; myRange) /* use item */

How it works…

The range interfaces are parameterized on the type of front, but otherwise work like any other class hierarchy. The implementation of the interface is automatically generated by inputRangeObject or outputRangeObject using reflection and code generation to build the most specific object possible from the given type.

As interfaces use virtual functions, including for all the (usually cheap) range properties, there's a performance penalty to polymorphic ranges. Typically, runtime polymorphic ranges run at about half the speed as their compile-time counterparts, and thus they should be avoided unless your use case requires them.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.222.182.66