On Thu, 12 Nov 2009 08:56:06 -0500, Denis Koroskin <2kor...@gmail.com> wrote:

On Thu, 12 Nov 2009 16:23:22 +0300, Steven Schveighoffer <schvei...@yahoo.com> wrote:

On Thu, 12 Nov 2009 08:22:26 -0500, Steven Schveighoffer <schvei...@yahoo.com> wrote:

On Tue, 10 Nov 2009 18:49:54 -0500, Andrei Alexandrescu <seewebsiteforem...@erdani.org> wrote:

I think the best option for toString is to take an output range and write to it. (The sink is a simplified range.)

Bad idea...

A range only makes sense as a struct, not an interface/object. I'll tell you why: performance.

Ranges are special in two respects:

1. They are foreachable. I think everyone agrees that calling 2 interface functions per loop iteration is much lower performing than using opApply, which calls one delegate function per loop. My recommendation -- use opApply when dealing with polymorphism. I don't think there's a way around this.

Oops, I meant 3 virtual functions -- front, popNext, and empty.

-Steve

Output range has only one method: put.

I was referring to range's ability to interact with foreach. An output range wouldn't qualify as a foreachable entity anyways (and rightfully so). Just covering all the bases.

I'm not sure, but I don't think there is a performance difference between calling a virtual function through an interface and invoking a delegate.

Yes, there is:

A delegate is equivalent to a struct member function call. (load data pointer (i.e. this), push args, call function) A virtual function uses a vtable to look up the function address, and then is equivalent to a struct member call. An interface function call is equivalent to a virtual call with the added penalty that you might have to adjust the 'this' pointer before calling.

But I agree passing a delegate is more generic. You can substitute an output range with a delegate (obj.toString(&range.put, fmt)) without any performance hit, but not vice versa (obj.toString(new DelegateWrapRange(&myput), fmt) implies an additional allocation and additional indirection per range.put call).

You can use scope classes to avoid the allocation, but you can't get around the virtual/interface call penalty.

But even if a range is a struct, it's simply a different form of delegate, one in which you undoubtedly call only one member function. Might as well use a delegate to allow the most usefulness.

-Steve

Reply via email to