ElementType and Other Range Templates
Learn the use of the ElementType range and get an overview of other range templates.
We'll cover the following
ElementType and ElementEncodingType
ElementType
provides the types of the elements of the range.
For example, the following template constraint includes a requirement for the element type of the first range:
void foo(I1, I2, O)(I1 input1, I2 input2, O output)
if (isInputRange!I1 &&
isForwardRange!I2 &&
isOutputRange!(O, ElementType!I1)) {
// ...
}
The previous constraint means I1 is an InputRange and I2 is a ForwardRange and O is an OutputRange that accepts the element type of I1.
Since strings are always ranges of Unicode characters, regardless of their actual character types, they are always ranges of dchar
, which means that even ElementType!string
and ElementType!wstring
are dchar
. For that reason, when needed in a template, the actual UTF encoding type of a string range can be obtained by ElementEncodingType
.
More range templates
The std.range
module has many more range templates that can be used with D’s other compile-time features. The following is a sampling:
-
isInfinite: Whether the range is infinite
-
hasLength: Whether the range has a length property
-
hasSlicing: Whether the range supports slicing i.e. with a[x…y]
-
hasAssignableElements: Whether the return type of
front
is assignable -
hasSwappableElements: Whether the elements of the range are swappable e.g. with
std.algorithm.swap
-
hasMobileElements: Whether the elements of the range are movable e.g. with
std.algorithm.move
This implies that the range hasmoveFront()
,moveBack()
, ormoveAt()
, depending on the actual kind of the range. Since moving elements is usually faster than copying them, depending on the result ofhasMobileElements
a range can provide faster operations by callingmove()
. -
hasLvalueElements: Whether the elements of the range are lvalues (roughly meaning that the elements are not copies of actual elements nor are temporary objects that are created on the fly)
For example, hasLvalueElements!FibonacciSeries
is false because the elements of FibonacciSeries
do not exist as themselves; rather, they are copies of the member current that is returned by front
. Similarly, hasLvalueElements!(Negative!(int[]))
is false because although the int
slice does have actual elements, the range that is represented by Negative
does not provide access to those elements; rather, it returns copies that have the negative signs of the elements of the actual slice. Conversely, hasLvalueElements!(int[])
is true because a slice provides access to the actual elements of an array.
The following example takes advantage of isInfinite
to provide empty
as an enum
when the original range is infinite, making it known at compile time that Negative!T
is infinite as well:
Get hands-on with 1400+ tech skills courses.