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.
Let's make use of runtime polymorphic ranges by executing the following steps:
inputRangeObject
or outputRangeObject
functions, passing an instance of any range to them.InputRange!type
or OutputRange!type
interfaces. The type there is the type returned by front
.cast
it to a more specific range type (for example, cast(RandomAccessRange)
) if more capabilities are needed.import std.range; InputRange!int myRange = inputRangeObject([1, 2, 3]); foreach(int item; myRange) /* use item */
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.
18.222.182.66