Overhauling the notion of output range

Steven Schveighoffer schveiguy at yahoo.com
Tue Jul 13 04:15:21 PDT 2010


On Mon, 12 Jul 2010 22:58:07 -0400, Andrei Alexandrescu  
<SeeWebsiteForEmail at erdani.org> wrote:

> On 07/12/2010 04:39 PM, Steven Schveighoffer wrote:
>> On Mon, 12 Jul 2010 17:25:43 -0400, Andrei Alexandrescu
>> <SeeWebsiteForEmail at erdani.org> wrote:
>>
>>> On 07/12/2010 02:41 PM, Steven Schveighoffer wrote:
>>>> I'm unsure how it will work either. I admit now that I didn't think
>>>> through how this will be used.
>>>
>>> It's very simple. As far as a user of an output range is concerned,
>>> they should write stuff like:
>>>
>>> put(r, '[');
>>> char[] someBuf;
>>> put(r, someBuf);
>>> put(r, ", ");
>>> put(r, ']');
>>>
>>> in confidence that things are reasonably efficient.
>>
>> How does that work for a range whose front() can be assigned a dchar?
>> Wait, it doesn't, because it won't compile.
>>
>> But wouldn't that be the same for a delegate that takes a dchar?
>>
>> I'm very confused at what you are trying to do. I expected that a char[]
>> would be a valid output range.
>
> Actually a char[] is not a valid output range. Overwriting  
> variable-length codes with other variable-length codes might mess up the  
> string.

Hm... I think it should be, and here is why.  Imagine this situation:

char[1024] buffer = void; // allocate some blank space on the stack
put(buffer, someInputRange);

But the above won't compile anyways, because a ref char[1024] isn't a  
range, and even if it was, it would be left in a state where it pointed to  
the uninitialized data.  What we need is a helper struct, and then we are  
covered.

char[1024] buffer = void;
CharBuilder builder(buffer[]); // defines put
put(builder, someInputRange);

So I think we are good.  Does Appender work here?

>
> Here's what I have. Works?
>
> void put(R, E)(ref R r, E e)
> {
>      static if (!isArray!R && is(typeof(r.put(e))))
>      {
>          r.put(e);
>      }
>      else static if (!isArray!R && is(typeof(r.put((&e)[0..1]))))
>      {
>          r.put((&e)[0..1]);
>      }
>      else static if (is(typeof(r.front = e, r.popFront())))
>      {
>          r.front = e;
>          r.popFront();
>      }
>      else static if (isInputRange!E && is(typeof(put(r, e.front))))
>      {
>          for (; !e.empty; e.popFront()) put(r, e.front);
>      }
>      else static if (is(typeof(r(e))))
>      {
>          r(e);
>      }
>      else static if (is(typeof(r((&e)[0..1]))))
>      {
>          r((&e)[0..1]);
>      }
>      else
>      {
>          static assert(false, "Cannot put a "~E.stringof~" into a  
> "~R.stringof);
>      }
> }

That is satisfactory, it encompasses what I was saying, thanks!

-Steve


More information about the Digitalmars-d mailing list