Subject: Re: [boost] An alternative approach to TypeErasure
From: Pyry Jahkola (pyry.jahkola_at_[hidden])
Date: 2012-06-24 17:53:47
On 2012-06-24 18:34:13 +0000, Steven Watanabe said:
> On 06/24/2012 08:13 AM, Dave Abrahams wrote:
>> Very interesting. Does either approach support operator overloading?
> Yes. I put quite a bit of effort into making
> sure that operator overloads would work
I started the work on operator overloading, as you might guess when
seeing the file
include/poly/operators.hpp (names in this file will definitely change)
I didn't get so far that poly::interface would actually recognize these
callables and create the corresponding operators for itself, but that
sure is possible.
More importantly, I'm still kind of missing the point of why the
feature of operator overloading is really needed. In essence: How
should binary operators behave? Steven's TypeErasure defines binary
operators such that only when the wrapped types of a and b are the
same, can you sum them up: "a + b".
But where would you use this kind of an "any", where only some of the
instances can be added up, and others cause undefined behavior?
Wouldn't you actually do the addition on the side where you know the
types, and not on the type-erased side?
Do we really have a real world use case that would prompt us to
implement features like operator overloading?
* * *
Before releasing more worms from the can of type-erased operators, I
must confess that I know still too little about the possible uses for
type erasure / expression problem / what you name it. What I propose is
we should look into how e.g. Haskell and Clojure programmers use their
type classes and protocols.
For one thing, I could only think of few examples where the interface
would have mutating functions. (Anybody care to throw in more examples?)
More typical use cases (that I could think of) are functions which read
the wrapped type (as const reference), and then either (1) return a
value, or (2) cause a side effect:
std::string(to_html_, self const &); // (1) "pure" function
void(print_, self const &, std::ostream &); // (2) side effect
Maybe if the whole interface is about wrapping some sort of computation
or side effect, it might make sense to have some non-const functions
using progress = interface<
std::size_t(total_progress_, self const &),
std::size_t(current_progress_, self const &),
void(run_for_, self &, std::chrono::microseconds)>;
Or maybe it's modeling a kind of a container and you can insert items into it:
using container = interface<
void(insert_, self &, std::size_t, content),
void(remove_, self &, std::size_t),
content &(at_, self &, std::size_t),
content const &(at_, self const &)>;
-- Pyry Jahkola pyry.jahkola_at_[hidden] https://twitter.com/pyrtsa
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk