I think you'll find that once you get used to the idea that char is for UTF-8, and ubyte is for other representations, it not only feels natural but the code becomes clearer.
As for invalid code points, you get to choose the behavior:
1. throw exception
2. use the replacement char
3. ignore it
All are valid in real life, and so D is accommodating.
As for invalid code points, you get to choose the behavior:
1. throw exception
2. use the replacement char
3. ignore it
All are valid in real life, and so D is accommodating.