Re: future of the C++
On Jul 10, 2:02 pm, Mathias Gaunard <loufo...@gmail.com> wrote:
On Jul 8, 4:37 am, George Neuner <gneun...@comcast.net> wrote:
[snip]
The problem is that C++ overload resolution only matches static types
at compile time, so there is no _good_ way to perform multiple
dispatch on runtime object types.
You don't seem to understand what I was talking about, so here is an
example.
Say you have, in ML
type btree = Leaf | Node of int * btree * btree
with variant, you express that as (it's been a while since I've used
recursive ones, but I think this syntax is correct)
struct leaf_t {};
typedef tuple<int, recursive_wrapper<_>, recursive_wrapper<_>> node_t;
typedef variant<leaf_t, node_t> btree_t;
In ML, to visit it, you write
match mytree with
Leaf -> do_something_for_leaf ()
| Node(v, lft, rgt) -> do_something_for_node v lgt rgt
;
With variant, you could write
apply_visitor(make_overload<void>(
[&](leaf_t) { do_something_for_leaf(); },
[&](node_t& n) { do_something_for_node(n.get<0>(), n.get<1>(),
n.get<2>()); }
), mytree);
(Not this also works to visit multiple objects at the same time)
How can this be done for n-ary function object? The above example
is just for 1-ary function. I guess you could argument that you
could just package an n arguments into one large tuple, but then
you'd have a very large apply_visitor expression since the number
of arguments would be the size of the cross product of the possible
concrete types for each "abstract" type in the argument list. By
"abstract" type I mean something like variant<C1,C2...,Cn>. The
corresponding set of concrete types would be {C1,C2,...,Cn}.
apply_visitor, from boost.variant, does internally the dispatch, then
casts the variant objects back to their real types, and finally calls
a polymorphic function object.
By generating that polymorphic function object through overloading
several monomorphic functions, you obtain syntax similar to that of
pattern matching.
The limitation of that technique is that you can't ask to match on
things like Node(_, Leaf, Leaf), but that kind of thing would still be
possible to do using a DSEL.
Which is a long-winded way to accomplish 1/3 of runtime multiple
dispatch ... namely it solves identification of the argument's runtime
type. You still need a way to describe function argument lists and to
match the list of variant arguments to the descriptions.
And overloading does just that; nothing prevents you however from
coding your own resolution scheme as a pure library implementation,
using a DSEL to describe what you want to match on.
http://article.gmane.org/gmane.comp.parsers.spirit.general/20146
Contains a link to a c++ multiple dispatch implementation. It does
what George calls "the 1/3 of runtime multiple dispatch" by one of 2
methods:
reify_visitor:
the GOF visitor pattern.
reify_switch
uses the boost preprocessing library to generate a switch
statement
It does this for each argument, resulting in a "packaging" of all the
arguments in a void** value wrapped in a
ptrs_target_source<C1,C2,...,Cn>, where C1,...,Cn arg the concrete
types corresonding to the abstract types of the original call. To
accomplish the last 2/3 of "runtime multiple dispatch" (according to
George, IIUC) it uses:
http://svn.boost.org/svn/boost/sandbox/variadic_templates/boost/function_types/can_be_called.hpp
to test whether the functor, F, passed to reify_apply template can be
applied to an argument list of type (C1,C2,...,Cn). If so, it does
the call, if not an exception is thrown.
This method involves a lot to template metaprogramming, and in that
sense, it's not a _good_ way; however, I'd be interested in hearing
what others think of it.
-regards,
Larry
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]