Handling arbitrary char ranges

ag0aep6g via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Wed Apr 20 12:29:22 PDT 2016


On 20.04.2016 19:09, Matt Kline wrote:
> 1. What is the idiomatic way to constrain the function to only take char
> ranges? One might naïvely add `is(ElementType!T : char)`, but that falls
> on its face due to strings "auto-decoding" their elements to dchar.
> (More on that later.)

Well, string is not a char range. If you want to accept string, you have 
to special case it. Rejecting string is an option, though. The caller 
would then have to make a char range from the string. There's 
std.utf.byCodeUnit for that.

> 2. The function fails to compile, issuing, "cannot implicitly convert
> expression (sendData[0..minLen]) of type string to void[]" on this line.
> I assume this has to do with the immutability of string elements.
> Specifying a non-const array of const elements is as simple as
> `const(void)[]`, but how does one do this here, with a template argument?

Looks like a compiler bug to me. It works when you do it in two steps:
----
string sendData = "foo";
void[] buf = new void[3];
immutable(void)[] voidSendData = sendData;
buf[] = voidSendData[];
----

I've filed an issue:
https://issues.dlang.org/show_bug.cgi?id=15942

> 3. Is this needed, or is auto-decoding behavior specific to char arrays
> and not other char ranges?

Auto-decoding is specific to arrays.

> 4. Is this a sane approach to make sure I'm dealing with ranges of
> chars? Do I need to use `Unqual` to deal with const or immutable elements?

is(Foo : char) also accepts byte, ubyte, bool, and user-defined types 
with an alias this to a char.

You don't need Unqual with `: char`. Since immutable(char) is a value 
type still, it implicitly converts to char. However, if you want to 
reject those other types, and only accept char and its qualified 
variants, then you need Unqual:
----
is(Unqual!(ElementType!bcu) == char)
----

> 5. This fails, claiming the right hand side can't be converted to type
> void. Casting to ubyte doesn't help - so how *does* one write to an
> element of a void array?

void[] is a bit of a special case. A single value of type void isn't 
really a thing. You can't write `void v = 1;`. Maybe use ubyte[] for the 
buffer type instead.

To do it with void[], I guess you'd have to slice things:
----
char c = 'x';
void[] buf = new void[1];
buf[0 .. 1] = (&c)[0 .. 1];
----

> Am I making things harder than they have to be? Or is dealing with an
> arbitrary ranges of chars this complex? I've lost count of times
> templated code wouldn't compile because dchar was sneaking in
> somewhere... at least I'm in good company.
> (http://forum.dlang.org/post/m01r3d$1frl$1@digitalmars.com)

I think your problems come more from wanting to accept string, which 
simply isn't a char range, and from using void[] as the buffer type.


More information about the Digitalmars-d-learn mailing list