Storing a range instance in a non-template class or struct can be difficult because the type isn't always obvious and is sometimes completely unavailable. Ranges are typically for temporary use, and thus they don't need to be stored for long and are usually eligible for auto
type deduction, but if you do need to store it, there are two options.
We can store a range as a data member by executing the following steps:
import std.range; InputRange!int rangeObj; rangeObj = inputRangeObject(your_range);
Remember, there is a performance penalty for this method, but it does have the advantage of being reassignable by different types of ranges as needed.
typeof
operator to get the range type out of the function, as shown in the following code:typeof(function_that_returns_a_range) rangeObj;
The code is as follows:
import std.algorithm; typeof(filter!((a) > 0)([1,2,3])) filteredRange; // declare it this() { filteredRange = filter!((a) > 0)([1, 2, 3]); // initialize it }
The typeof
operator can be used anywhere in D where you need a type. When passed a variable or expression, it returns the static (compile-time) type of that variable or expression. When passed a function call, it returns the return type of the function. This can be used as a tool in compile-time reflection, for convenience with complex types, or generic code.
The typeof
operator works even when the type is not otherwise available, such as a struct in a module you haven't imported, or if the type has no name. In Phobos, many range functions return nested structs, as shown in the following code:
auto hiddenType() { struct Foo { } return Foo(); } auto test = hiddenType(); /* test has a type whose definition is not available outside the hiddenType function. Calling it Foo or hiddenType.Foo will not work because types declared inside functions are not available outside. */
This is sometimes called a Voldemort type, referencing a fictional character whose name is not allowed to be spoken.
When using auto
type deduction, everything just works; however, if you need to declare a variable of that type before it is used, this presents a problem. The typeof
operator is a solution, as shown:
typeof(hiddenType()) test = hiddenType(); // works!
As ranges often have complex or hidden type names, typeof
may be the only way to refer to them without an auto
type deduced variable.
3.147.72.74