From: Martin B. on
Seungbeom Kim wrote:
> On 2010-07-10 07:14, Andrew wrote:
>> On 7 July, 20:16, Walter Bright <newshou...(a)digitalmars.com> wrote:
>>> Mathias Gaunard wrote:
>>>> I personally don't understand the point of non-recoverable exceptions
>>>> at all. If they're non recoverable, it means it is something that
>>>> should *never* happen, and therefore is a bug in the program itself.
>>>> The program might as well abort and terminate directly.
>>> Yes, you're quite right.
>> I reckon this is true >90% of the time. However, I once (relatively
>> [...] log the occurence in our log and then carry on, rather than
>> disconnect the other hundreds of clients.
>>
>> For this reason, in the implementation of our functionality in the
>> server, we defined an exception that meant 'a programming error has
>> been detected'. I think we called it AssertionFailure. We threw this
>> where other people might have used the C assert macro. We arguments
>> [...]
>
> If a bug that reveals itself in processing one request can terminate
> the whole server [...]Shouldn't they be
> processed by separate processes so that termination of one doesn't
> affect the others? [...]
>

Should yes. But that doesn't help the developers having to maintain a
system that doesn't. (And/or can't for whatever reasons.)

> Besides, If a programming error has been detected, chances are that
> some internal data structure has already been corrupted, and it doesn't
> seem like a sound approach to let it continue and process new requests.
>

Chances are. But from what I see in the field they are quite small. My
point being that for the other "processes" to be affected some "global"
state has to be corrupted. Most of the time though most of such bugs I
see are of a rather local nature, i.e. a function has been called with
an invalid parameter set (due to insufficient testing over all execution
paths, etc.), some nullptr is dereferenced because an obscure error
condition has not been anticipated, and so on.
Being able to handle this without bringing the whole system down can be
very helpful IMHO.

cheers,
Martin

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Larry Evans on
On Jul 10, 2:02 pm, Mathias Gaunard <loufo...(a)gmail.com> wrote:
> On Jul 8, 4:37 am, George Neuner <gneun...(a)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! ]

From: Mathias Gaunard on
On Jul 12, 2:14 pm, Larry Evans <cppljev...(a)gmail.com> wrote:

> > 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?

apply_visitor(make_overload<void>(
[&](leaf_t, leaf_t) { do_something_for_leaf_and_leaf(); },
[&](node_t& n, leaf_t)
{ do_something_for_node_and_leaf(n.get<0>(), n.get<1>(),
n.get<2>()); },
.. other cases if you want to handle them...
), my_first_tree, my_second_tree);

I think however the implementation may be limited to binary
visitation, because it was judged at that time that with then current
meta-programming techniques it was not worth the effort to generalize
it to n.


> reify_switch
> uses the boost preprocessing library to generate a switch
> statement

There is a switch library within boost that already generates switch
statements...


> 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.

I don't even understand where that void** comes from.


> it uses:
>
> http://svn.boost.org/svn/boost/sandbox/variadic_templates/boost/funct...
>
> 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.

You could simply add an operator()(...) overload to your functor, no
need for needlessly complicated introspection machinery.

Throwing an exception is also a bad idea. You should abort, since this
is a programming error. (but then, quite a few other boost components
do that mistake too)


> 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.

Since it basically does a subset of what boost.variant does and is
less portable, it's not terribly useful is it?
Having two implementation strategies is confusing. What are the
advantages of one over the other?


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Walter Bright on
nmm1(a)cam.ac.uk wrote:
> Most of the common C/C++ aspects were
> neither the physical constness of objects in memory nor logical
> constness, but restrictions on lvalue use to improve optimisability
> (again the original C90 rationale makes that clear).

Which it failed at, as the compiler cannot make use of const-as-type-constructor
to optimize, only const-as-storage-class.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Mathias Gaunard on
On Jul 11, 3:49 pm, George Neuner <gneun...(a)comcast.net> wrote:
> On Sat, 10 Jul 2010 13:02:44 CST, Mathias Gaunard <loufo...(a)gmail.com>
> wrote:
>
> >On Jul 8, 4:37 am, George Neuner <gneun...(a)comcast.net> wrote:
> >The point of a closure-like device is to be able to call it, combine
> >it with other closures, and pass it around to code that has no
> >knowledge of what the closure is or does, except that it accepts the
> >types it gives.
>
> Yes.
>
> >> C++'s lack of <dynamic typing> prevents easy use of <things you can
> >do when you have dynamic typing>.
> >(Edited by myself)
>
> >Unrelated.
> >The fact Lisp is dynamically typed doesn't mean that this is what
> >functional programming is about.
>
> First of all, Lisp is not dynamically typed, it is _statically_,
> _latently_ typed in the same way that C++ objects are.
> Lisp variables are of type "T" which is a sum of all types.

If the type of a variable depends on runtime characteristics, then
they are dynamically typed.

It can indeed be claimed that all variables in a dynamically-typed
language are statically the sum of all types, but the choice of which
type it is in particular remains dynamic, so it's nothing but an
implementation detail for a static representation.



> Second, I mentioned Lisp to provide an example of useful functionality
> that C++ lacks and which can only be implemented by using runtime
> argument types.

Yet you tried to pass that as a functionality of functional
programming.


>
> >The best way to do multiple dispatch is certainly to use dynamic
> >typing.
>
> Again with the "dynamic" ... you meant "runtime".

I meant what I said.
Maybe we don't use the same definition, but there seems to be no clear
and agreed-upon definition of such things anyway.


> >CLOS does it very nicely.
>
> Yes. And so could C++ if it cared to.

As I said, Lisp is dynamically typed, and that makes things entirely
different.
As you said yourself, this is the same as having a type that is the
sum of all possible types. This is what variant is (or can be), but it
doesn't -- and never will -- integrate fully with the language: you
need to tag objects beforehand. That's because C++ is not dynamically
typed, even if it does have some of that as part of OOP/virtual
functions/rtti (which I'm sure you will not consider dynamic typing at
all, after all it's just /runtime/ binding), which is more of a bad
paradigm than anything else.


> >You don't seem to understand what I was talking about, ...
>
> I understand exactly what you are talking about.

Yet I'm convinced you don't and don't even want to try to -- since
you're convinced you know better, after all how more complicated than
Lisp or Smalltalk can C++ be? --, which means I will stop
participating here.


> I'm disagreeing with
> your assertion that it is irrelevant to C++ programming and also with
> your assertion that the visitor pattern using Boost::variant is a
> reasonable implementation. I will agree it is AN implementation.

C++ is powerful enough that it doesn't need every craziness built into
the language, as you can express any sub-language as a library
(remember that domain-specific embedded language thing?).


> Patterns (in the Gang-of-4 sense) exist primarily to compensate for
> the lack of ability of a language to efficiently or elegantly express
> something that many of its developers consider important.
>
> The "visitor" pattern [...]

This has nothing to do, at all, with the Gang-of-4 visitor. Please,
let's stay away from this horror.


> I'm not disputing the existence of this ABI ... I am disputing your
> assertion that it is an "industry standard". I have no doubt that the
> coalition would like it to be a standard, but it is quite likely only
> ever to be used for x86.

For example, I believe this ABI is used at a high-level into GCC, and
is thus applied to all its backends, which comprise all the
architectures that ever mattered.
Most other major compilers do the same.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]