Question

I'm trying to use the slice operator to obtain a slice of the return value of the take function from std.range. My code:

auto tempChunk = ['a', 'b', 'c', 'd'];
auto a = tempChunk.take(3);
writeln(a[0..2]);

As Take!R in this case is just an alias for char[], I'd expect this to compile. However, the compiler tells me that Take!(char[]) cannot be sliced with []. Taking another example:

int[] arr1 = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]; 
auto s = arr.take(5);
writeln(s[0..4]);

This will compile and run without a problem, printing [1, 2, 3, 4, 5]. I am completely confused at this point as to why the first example won't work, while the second does.

Was it helpful?

Solution

take template uses hasSlicing to determine if slice of input can be returned instead of Take!R struct. Checking actual return types makes it a bit more clear:

import std.range, std.stdio;

void main()
{
    auto chararr = ['a', 'b', 'c', 'd'];
    auto a = chararr.take(3);
    writeln( typeid(typeof(a)) );

    auto intarr = [ 1, 2, 3, 4 ];  
    auto b = intarr.take(3);
    writeln( typeid(typeof(b)) );
}

// Output:
// std.range.Take!(char[]).Take
// int[]

hasSlicing is explicitly instructed to return false for all "narrow strings" - those, which element may not represent single character, but a code point (char and wchar based ones).

Now, here is where my speculations start but I suppose it is done to prevent accidental creating of malformed UTF-8 & Co strings using slicing. Better to use dchar[] if you do not have any real need in char[].

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top