On Friday, 20 September 2013 at 07:39:47 UTC, QAston wrote:
On Thursday, 19 September 2013 at 22:46:09 UTC, Andrei
Alexandrescu wrote:
On 9/19/13 3:18 PM, Szymon Gatner wrote:
I had similar thoughts when watching GoingNaive 2013:
http://bartoszmilewski.com/2013/09/19/edward-chands/
Nice piece.
I was more and more scared with every talk and now I am
valualizing my
polymorphic types a'la Sean Parent
That I think is sketchy advice.
Andrei
What Sean Parent does in his value semantics talk is basically
an interface adapter for a struct, wrapped in a struct
providing implicit conversions.
By using structs by default and adapting them to interfaces as
needed you get to have the smallest possible overhead on a
single function call - either no virtual dispatch or 1 virtual
dispatch. When writing adapters to interfaces you get 2 or more.
The struct was only an example, obviously you can use proper
class implementations with data hiding etc. You will also get at
least 1 virtual call because a "concept" is always an abstract
class.
That being said, I've been using this technique in other places
in my code this far too, for example: my C++ ranges (yeah idea
stolen from D) are templates so can be composed for free but
there are abstractions like InputRange<> which "erase" (this word
is stupid btw, no type is erased really) underlying type and
provide convenient abstraction in places. I also use this
technique for my std containers. Vector is a std::vector with
polymorphic allocator, again it holds Allocator<> by value but
underlying implementation is (often composition) of allocator
templates. In allocator's case I do explicitly want container
alloc to be polymorphic type so that my interfaces never depend
on allocator type.
Difference now for me is that I did sometimes turn value types
into polymorphic types using this technique (like with
allocators) but it never occurred to me that other wan can be
beneficial too.
The other benefit is that approach is reducing dependencies you
need to know about when you use the wrapper type - the approach
would not work in D due to lack of argument dependent lookup so
you need to write the adapter type (for a particular type you
want to convert) yourself anyways. And I think it's better that
way.
In the end the whole thing is just adapter design pattern
applied to C++.
Well Adapter is suppose to *change* interface to adapt to client
needs so this is a bit of a strech to call it that here, but
yeah, this technique called ("external polymorphism" idiom) can
be used to adapt . This really just is a (smart)pointer with a
full interface of underlying object (which also adds benefit or
using "." instead of "->" on target).