Thursday, November 26, 2009

comp.lang.c++ - 24 new messages in 10 topics - digest

comp.lang.c++
http://groups.google.com/group/comp.lang.c++?hl=en

comp.lang.c++@googlegroups.com

Today's topics:

* deducing the return type of a function call... - 1 messages, 1 author
http://groups.google.com/group/comp.lang.c++/t/0f45c70f160da18c?hl=en
* I don't have to tell you... - 4 messages, 3 authors
http://groups.google.com/group/comp.lang.c++/t/f615b948e5cca45b?hl=en
* a compiler for managed c++ - 4 messages, 4 authors
http://groups.google.com/group/comp.lang.c++/t/2a6eb8a0c00c78fe?hl=en
* in reply to: DWORD and bool to binary - 1 messages, 1 author
http://groups.google.com/group/comp.lang.c++/t/82fe3c2b8fefe33f?hl=en
* s - 1 messages, 1 author
http://groups.google.com/group/comp.lang.c++/t/94761f909a9f2ee2?hl=en
* Article on possible improvements to C++ - 5 messages, 3 authors
http://groups.google.com/group/comp.lang.c++/t/e46e9b3e07711d05?hl=en
* Portability and marshalling integral data - 1 messages, 1 author
http://groups.google.com/group/comp.lang.c++/t/d7831b8e84cbb8c3?hl=en
* How to get an insertion hint for an unordered associated container? - 1
messages, 1 author
http://groups.google.com/group/comp.lang.c++/t/21e47512ffcaf8a2?hl=en
* Why do some code bases don't use exceptions? - 5 messages, 1 author
http://groups.google.com/group/comp.lang.c++/t/c255001068888229?hl=en
* Multiple inheritance and pointer equivalence - 1 messages, 1 author
http://groups.google.com/group/comp.lang.c++/t/6ce10e4cd7c07869?hl=en

==============================================================================
TOPIC: deducing the return type of a function call...
http://groups.google.com/group/comp.lang.c++/t/0f45c70f160da18c?hl=en
==============================================================================

== 1 of 1 ==
Date: Thurs, Nov 26 2009 3:34 pm
From: "Alf P. Steinbach"


* James:
> "Frank Neuhaus" <fneuhaus@uni-koblenz.de> wrote in message
> news:hemspm$3hv$1@cache.uni-koblenz.de...
>> Hey,
>>
>> "James" <no@spam.invalid> schrieb im Newsbeitrag
>> news:hemrjd$jbm$1@aioe.org...
>>> I am struggling to find a way to get around having to explicitly pass
>>> a return type for the following callback scheme I am playing around
>>> with. Here is some sample code:
>>
>> Maybe this can help you?
>> http://www.boost.org/doc/libs/1_35_0/libs/type_traits/doc/html/boost_typetraits/reference/function_traits.html
>>
>>
>
> How in the heck does it determine all of those traits? Anyway, I don't
> think it would work for me unless I could do something like:
>
>
> int foo()
> {
> return 0;
> }
>
>
> void blah()
> {
> typedef function_traits<foo>::result_type return_type;
> }
>
>
> and have return_type be an int.
>
>
>
> AFAICT, that's just not going to work here.
>
>
> What am I missing?

Difficult to say since you haven't made your design requirements very clear.

But in general you can't portably deduce function result types in C++98 without
"registering" all relevant types first (you can however do that in C++0x).

Anyway, perhaps this helps:


<code>
#include <stdio.h>

template< typename Result >
class AbstractInvokable
{
public:
virtual Result operator()() const = 0;
};

template< typename Result, typename Arg >
class Invokable
: public AbstractInvokable< Result >
{
private:
Arg myArg;
Result (*myF)( Arg );
public:
Invokable( Result f( Arg ), Arg a )
: myArg( a )
, myF( f )
{}

virtual Result operator()() const
{
return myF( myArg );
}
};

template< typename Result, typename Arg >
Invokable< Result, Arg > bind( Result f( Arg ), Arg a )
{
return Invokable< Result, Arg >( f, a );
}


int foo( int x ) { return printf( "f(%d)\n", x ); }
void blah( char const* s ) { printf( "blah(\"%s\")\n", s ); }

int main()
{
AbstractInvokable<int> const& f = bind( foo, 42 );
AbstractInvokable<void> const& b = bind( blah, "whoopie doo!" );

f();
b();
}
</code>


Cheers & hth.,

- Alf

==============================================================================
TOPIC: I don't have to tell you...
http://groups.google.com/group/comp.lang.c++/t/f615b948e5cca45b?hl=en
==============================================================================

== 1 of 4 ==
Date: Thurs, Nov 26 2009 3:54 pm
From: "Balog Pal"


"Alf P. Steinbach" <alfps@start.no>

> The incompetence of experienced people is a problem with no known
> solution.
>
> You say that at least some people, and I assume that you mean experienced
> ones, expect the language to behave in a nonsensical way, like some other
> language they're familiar with.

I don't say that. :) The observation is that people just drop in the
virtual call. And start to thinker on the language behavior after getting
burnt.

And not necessarily "expect" the thing work this or that way. The pragmatic
way is to do the work anyway instead of dreaming about a different world. :)

Guidelines just help to minimize the wasted time. Not going there in the
first place or having the relevant info faster at least.

> And it seems that you're implicitly arguing that because of their
> nonsensical expectation the safe behavior is a problem.
>
> That since they practically can't be made competent, the language should
> be dumbed down to their level, removing safety features they fail to
> understand.

That's shadow-boxing. ;-)

I don't have a problem of how C++ deals with virtuals, and most likely would
chose the same behavior. And I also agree with the guideline that states
don't call virtuals in the situation.

Those who are competent and found the rare situation it makes sense or is is
just safely irrelevant will hardly be bothered by it.

>> In the real-life and not the technical sense. People are (appear) just
>> not aware that in ctor and dtor different rules apply, and expect the
>> code just work by magic -- as it does in every other context.
>>
>> The thing is on the FAQ is exactly for that: too many tried and got
>> surprized. Or even call 'foul' for calling the 'wrong' function.
>
> No, the FAQ is mainly for novices.
>
> A novice may expect C++ to work like some other language, e.g. like Java.
>
> An experienced C++ programmer who expects that, however, is incompetent.

Sure. This has nothing to do with the point I made.

I am competent in programming and C++. I do know the behavior of virtuals.
Including this thing. I know it for ages, and at the pioneering period
worked even with the assy code of ctors/dtors. To know the exact point where
the VMT pointer is replaced (effectively changing the actial type of the
object at hand).

Yet, I recall at least one situation from my work I got hit by the related
problem -- having the wrong (meaning not the *intended*) function called
form a base destructor. Wasn't a big deal, and realized it in the first run
(probably it was a pure virtual with a noisy report).

But well demonstrates that shit just happens. ;-))

> I have on some occasions dumbed down code so that it "should" be grokkable
> even by idiots.

We know that is a futile effort, as nature immediately creates an advanced
idiot. And starts cloning it too.

>>> It's a not uncommon scenario. The mentioned bugs in Java programs are
>>> mainly due to this scenario occurring often in actual code. In C++ it's
>>> no problem. :-)
>>
>> In java the manifest problem is dealing with half-baked object in the
>> expected function.
>> In C++ it manifests by arriving in Self::foo(). What is way easier to
>> discover and rearrange the design.
>
> You don't want to rearrange the correctly working C++ code.
> So, C++: zero time.

Computers do what is ordered, not what was intended. The "correct" code
would be with the intended behavior. The fact that the C++ part safely does
the unintended thing will not make it fly.

>> The usual rearrangement is to pass the work up, and make the result of
>> the former virtual call a parameter of the ctor...
>> And for dtors you sigh, and copy the code in the derived dtors...
>
> This doesn't make sense. It seems you have some problem and some
> particular based-on-misconceptions non-working solution to that problem in
> mind. Don't blame that on the language: blame it on a fixation on a
> non-working solution.

You can put it that way if you like, it won't make the problem go away.
The mind works in an interesting way. See the examples of the optical
illusions. (or how is that called when you see straight lines as curved,
equal length as different, same color as massively darker in a properly
created picture).

Similar fallacy is to expect things to "work". There was recently a
reference to Mark Rosewater's evil creations here or on a neighboring forum.
And that is exactly true.

And the more commonly a feature just does the job the less we think there
are limits.

>> In both cases the call to virtual gets removed from the code, like
>> obeying the "don't". :)
>
> What you're saying seems to be that you have suffered from the "C++ works
> like Java" misconception, and fixed that by removing calls that you
> believed would end up in a derived class.
>
> Well that's not something to blame C++ for.

That is what I'm saying from the start. This problem is not related to C++,
but to the general thinking of virtuals. And a related genuine, theoretic
limitation.

Languages could create different behaviors, but none of them would be good
for all the cases.


== 2 of 4 ==
Date: Thurs, Nov 26 2009 10:19 pm
From: Howard Beale


Alf P. Steinbach wrote:

> * Howard Beale:
>> Alf P. Steinbach wrote:
>>
>>> * Balog Pal:
> You made several factually incorrect claims, as I count it four of
> them in the single paragraph of yours that I quoted in my first
> response:
>
> * Howard Beale:
>> In what order are constructors and destructors called? Answer - in
>> whatever order ANSI/ISO chooses to call them, and [1] you'll never
>> know just by looking at your code, and [2] you'll never be able to
>> change it
>> if it doesn't suit you. Does it matter? Yes - the choice that was
>> made means that [3] you should never call virtual functions from a
>> constructor or destructor, even though [4] the language will allow
>> you to do so with no warning, just incorrect behavior.
>
> To which of these four incorrect claims (if any) are you referring?
>
> None of them are supported by the FAQ.

Well, most of them don't need to be supported by anything, as they are
common knowledge.

[1] As in the example I gave (and any example that could be given), you
wouldn't know, by just looking at the code, that you're going to get the
wrong output. You would have to also know about the order in which
constructors / destructors are called, which is exactly what is at issue
here. You may say that the output isn't "wrong," but I personally
believe that if the area of a circle is pi*r^2 during its entire
existence, then it's area should also be pi*r^2 when it is being created
or destroyed. And most programmers, unaware of this little gotcha,
would say the same thing. You, being a C++ proponent and expert, know
differently, but most programmers prefer consistent behavior. Yes, I'll
grant that programmers also want safety, but it is entirely possible for
a compiler to safely allow virtual methods during construction and
destruction.

[2] Do you know of a way to change the order in which constructors /
destructors are called? I don't, outside of writing a new compiler.

[3] I guess "never" is a strong word, so I can meet you half way on this
statement, I suppose, and just say "don't expect virtual methods to work
correctly when called from a constructor or destructor, so call them
there only if you want incorrect behavior." Seems like a silly caveat.
If you feel that the behavior that I describe isn't "incorrect," then
you're too tolerant in your definition of correctness.

[4] My compiler doesn't give me any warning when I call a virtual method
from a constructor or destructor. I don't know what more to tell you.


== 3 of 4 ==
Date: Thurs, Nov 26 2009 10:19 pm
From: Howard Beale


Joshua Maurice wrote:

> Now, I know you're just trolling, but I'm easily baited.

... and also unaware of the movie "Network." It was a goof on a famous
speech in that movie. It was mostly exaggeration and silliness. The first
reply to it included a link to the video. But what I said at the end,
after the speech, was sincere.


== 4 of 4 ==
Date: Thurs, Nov 26 2009 11:16 pm
From: "Alf P. Steinbach"


* Howard Beale:
> Alf P. Steinbach wrote:
>
>> * Howard Beale:
>>> Alf P. Steinbach wrote:
>>>
>>>> * Balog Pal:
>> You made several factually incorrect claims, as I count it four of
>> them in the single paragraph of yours that I quoted in my first
>> response:
>>
>> * Howard Beale:
>>> In what order are constructors and destructors called? Answer - in
>>> whatever order ANSI/ISO chooses to call them, and [1] you'll never
>>> know just by looking at your code, and [2] you'll never be able to
>>> change it
>>> if it doesn't suit you. Does it matter? Yes - the choice that was
>>> made means that [3] you should never call virtual functions from a
>>> constructor or destructor, even though [4] the language will allow
>>> you to do so with no warning, just incorrect behavior.
>> To which of these four incorrect claims (if any) are you referring?
>>
>> None of them are supported by the FAQ.
>
> Well, most of them don't need to be supported by anything, as they are
> common knowledge.
>
> [1] As in the example I gave (and any example that could be given), you
> wouldn't know, by just looking at the code, that you're going to get the
> wrong output. You would have to also know about the order in which
> constructors / destructors are called, which is exactly what is at issue
> here. You may say that the output isn't "wrong," but I personally
> believe that if the area of a circle is pi*r^2 during its entire
> existence, then it's area should also be pi*r^2 when it is being created
> or destroyed.

I'm not sure what you mean by "wrong output".

You gave an incomplete example. From the output you asserted I and one other
guessed what the missing parts would have to be. That seems to indicate that it
isn't hard at all to relate C++ code to effect and vice versa, re these issues.

Regarding values of member variables or sub-objects, they simply do not exist
before creation or after destruction.

> And most programmers, unaware of this little gotcha,
> would say the same thing. You, being a C++ proponent and expert, know
> differently, but most programmers prefer consistent behavior.

The behavior in C++ is fully consistent.

It would be erronous to invoke methods on a chunk of memory that doesn't satisfy
the assumptions of the methods.

That's what happens in e.g. Java.

And so during T construction and destruction the most derived class, the
object's dynamic type, is T. That's because during construction, any more
derived type's subobject has not yet been initialized, and so doesn't formally
exist, it's just raw memory. And during destruction, any more derived type's
subobject has already been destroyed, hence doesn't formally exist any more.

So the C++ rule is extremely simple: at any time a virtual call invokes the most
derived class' implementation of the method.

The calls are virtual.

And they go to the correct place at any time.


> Yes, I'll
> grant that programmers also want safety, but it is entirely possible for
> a compiler to safely allow virtual methods during construction and
> destruction.

C++ does allow virtual calls during construction and destruction.

What's more, C++ actively supports such calls.

It's possible that you have some misconception that calls are not virtual during
construction and destruction, but they are. The only thing you have to keep in
mind is what exist at these point. Happily C++ won't let you do the Wrong Thing.

Post-construction and pre-destruction is however a bit hard to arrange in C++,
and some people, in particular Andrei Alexandrescu, have argued that it should
be made much easier and automated (e.g. you get into this issue with certain
GUIs like X11).

I'm not sure about that. I think making it much easier would lead to it being
employed for general two-phase construction and destruction by those who tend to
choose the short time-frame easy way. Sort of like making goto easier.


> [2] Do you know of a way to change the order in which constructors /
> destructors are called? I don't, outside of writing a new compiler.

Constructors and destructors are called in a very well defined sequence, except
for what's known as the "static initialization fiasco".

Apart from that issue you specify the construction/destruction order by
declaration order.

When that doesn't suffice you use dynamic allocation.

If you have any particular example/problem, why don't you post it.


> [3] I guess "never" is a strong word, so I can meet you half way on this
> statement, I suppose, and just say "don't expect virtual methods to work
> correctly when called from a constructor or destructor, so call them
> there only if you want incorrect behavior." Seems like a silly caveat.
> If you feel that the behavior that I describe isn't "incorrect," then
> you're too tolerant in your definition of correctness.

It's not a question of feeling.

It's incorrect to invoke methods on non-existent objects.

The behavior you crave, undefined behavior, is simply incorrect by any
reasonable measure of correctness.


> [4] My compiler doesn't give me any warning when I call a virtual method
> from a constructor or destructor. I don't know what more to tell you.

The compiler shouldn't warn you. You're not doing anything wrong (at least as
you describe it!). It's well-defined in C++.


Cheers & hth.,

- Alf

==============================================================================
TOPIC: a compiler for managed c++
http://groups.google.com/group/comp.lang.c++/t/2a6eb8a0c00c78fe?hl=en
==============================================================================

== 1 of 4 ==
Date: Thurs, Nov 26 2009 4:35 pm
From: Johnson


I am asking a beginner's question.

Is there any free compiler (or toolchain) for Managed C++ codes
available for Eclipse? I have a project written in managed c++, and I
don't want to be tied to Microsoft any more.

Thank you.

Johnson


== 2 of 4 ==
Date: Thurs, Nov 26 2009 6:48 pm
From: red floyd


Johnson wrote:
> I am asking a beginner's question.
>
> Is there any free compiler (or toolchain) for Managed C++ codes
> available for Eclipse? I have a project written in managed c++, and I
> don't want to be tied to Microsoft any more.


Then don't write in Managed "C++" (note the quotes).


== 3 of 4 ==
Date: Thurs, Nov 26 2009 7:04 pm
From: "BGB / cr88192"

"Johnson" <gpsabove@yahoo.com> wrote in message
news:hen6t5$2cit$1@adenine.netfront.net...
>I am asking a beginner's question.
>
> Is there any free compiler (or toolchain) for Managed C++ codes available
> for Eclipse? I have a project written in managed c++, and I don't want to
> be tied to Microsoft any more.
>
> Thank you.
>

managed C++ is, well, an MS product to bridge C++ to .NET...

the way to break free of MS then, is not to write in Managed C++, but
instead to write in plain C++...

OTOH, Eclipse is an IDE, and AFAIK itself does not manage the compilers
directly (although, AFAIK, it does do its own Java compilation). however, I
really don't know as personally I have never really felt much need to make
use of IDEs...


> Johnson


== 4 of 4 ==
Date: Thurs, Nov 26 2009 7:04 pm
From: Andrew Tomazos


On Nov 27, 1:35 am, Johnson <gpsab...@yahoo.com> wrote:
> I am asking a beginner's question.
>
> Is there any free compiler (or toolchain) for Managed C++ codes
> available for Eclipse? I have a project written in managed c++, and I
> don't want to be tied to Microsoft any more.

This may be relevant:

http://www.mono-project.com/CPlusPlus

Enjoy,
Andrew

--
Andrew Tomazos <andrew@tomazos.com> <http://www.tomazos.com>

==============================================================================
TOPIC: in reply to: DWORD and bool to binary
http://groups.google.com/group/comp.lang.c++/t/82fe3c2b8fefe33f?hl=en
==============================================================================

== 1 of 1 ==
Date: Thurs, Nov 26 2009 4:38 pm
From: Ian Collins


Chris M. Thomasson wrote:
>
> Indeed... Humm, well I guess the OP could try something crazy like this:

I don't think such guesswork will help an OP who looks totally lost!

--
Ian Collins

==============================================================================
TOPIC: s
http://groups.google.com/group/comp.lang.c++/t/94761f909a9f2ee2?hl=en
==============================================================================

== 1 of 1 ==
Date: Thurs, Nov 26 2009 7:28 pm
From: spamkillercc


s

==============================================================================
TOPIC: Article on possible improvements to C++
http://groups.google.com/group/comp.lang.c++/t/e46e9b3e07711d05?hl=en
==============================================================================

== 1 of 5 ==
Date: Thurs, Nov 26 2009 7:48 pm
From: paulto


dragan wrote:
[snipped]
>> Quite a bit of code will you need to properly destroy automatic
>> objects (which is quite often the required part of "error handling".
>> If handling of an error does not require stepping way back, that
>> error can be IMHO renamed to "yet another condition arising at normal
>> course of given business").
>
> Another simple answer from moi: RAII. Problem solved. RAII and exceptions
> are orthogonal concepts. RAII works as good with other error handling
> strategies as it does with exceptions.
RAII is a great idea but you need something to kick off the destructors.
It may be an important component of error handling strategy but
exception or something else is needed to actually kick off object
destruction if error processing requires changing the context outside of
normal flow control operation.

>> Essentially to me it sounds like: I prefer not to mistake business
>> requirements for errors.
>
> I just meant that I don't want to use the complex thing when another simple
> thing will work just fine.
see below..

>
>> And I could not agree with your more if
>> that's what you mean. To me an error means: I can't continue this
>> action. Now what am I going to do? At this point, to have at least
>> the second choice (the first is to terminate the program and it does
>> not require exceptions),
>
> Termination is only a choice in application code, not in library code. A
> library has to propogate or handle the error. Maybe if a precondition is
> violated you can make a case for termination from a library, not sure.
see below...

>
>> a robust context-switching mechanism is
>> needed (longjmp/setjmp, EPOC32/Symbian's "Leaves" with home-made
>> cleanup stack etc -- you name it).
>
> I wouldn't call setjmp/longjmp a "context switching mechanism", but I know
> what you meant. setjmp/longjmp is not an option in C++ because destructors
> aren't called during "the unwinding" of the "call stack".
Exactly my point. It won't automatically, you will have to hand-craft
some stupid mechanism like EPOC32/Symbian cleanup stack and never forget
put your important objects on it. I am just saying: for error processing
some mechanism of context-switching is needed (BTW longjmp/setjmp is
context-switching: the context in this case are the registers including
instruction pointer or equivalent and stack frame pointers or
equivalents. In practice, it's not enough as you want application-level
"unwinding" of automatic objects as you change the stack pointers or
equivalents; that's why I am saying exceptions are convenient and cheap
without obvious drawbacks for the purpose (as long as you do not require
more flexibility in selection of error processing code targets than
exception give you), library-based cleanup-stack is worse and
longjms/setjmp is still worse.. )

>
>> In most situations where the
>> failed "action" is not a separate "task" (whatever this means -- a
>> thread, a process or whatever -- in which case you could send a
>> message to another task and terminate the failed task),
>
> Doesn't appear to be an option because that won't "unwind the stack".
If you terminate the process, the automatic objects are destroyed; if
the "task" is something else, you are right, it's on you again :-).
That's again why I say exceptions are convenient.

>
>> exceptions
>> seem to be the most convenient and least costly (in terms of
>> programming/code maintenance) mechanism.
>
> That's one way to do it, yes. I'm sure there are others, but that
> necessarily commits you to using more than one EH thing.
I mentioned few above; but don't know anything as convenient as exceptions.

>> I don't do large-scale development and I have a toolbox full of
>>> error-handling techniques. I never understood this quest for "one
>>> and only one" when that is hardly ever appropriate: one error-management
>>> mechanism, one "standard" library, one<your choice here>...
>> See above.. I am not sure about you definition of an error though.
>
> I'm not either, LOL! ;) I've never sat down and wrote a definition of what
> an error is, but I agree with the general usage of the term as used in any
> of a number of books. But then again, errors are application-specific too
> and categorizing and defining and handling them is application-specific then
> also.
>
>>
>>>
>>>
>>> Locally handle-able conditions (errors)
>> This is telling.. what is you definition of an error as opposed to any
>> other "locally handle-able" condition?
>
> I don't want to get into a glossary debate.
I am not trying going there either; but we seem to be talking about
different things when we mention "error" term and this is not
productive. I would suggest to exclude A "locably-handleable" conditions
from the discussion. I do not see a reason for segregating them into a
separate category of "errors" from other application-level conditions;
you seem to argue exceptions is not the best way of processing them; I
do not challenge this at all, I just do not call these "business cases"
or "uses cases" "errors".

>
>>> are much more numerous than global errors handle-able appropriately
>>> by a technique such as set_new_handler.
>
>> Again, how do you destroy C++ local objects with using a handler?
>
> Well, perhaps you can resume after the handler runs if that is how your
> handler system works.
See above paragraph this time :-).

> If still no go, RAII time to do it's thing.
So, how do you kick-off the destructors for objects you initialized
under RAII paradigm?

> How you
> setup functions to do cleanup is a stylistic preference. A few macros and a
> goto macro perhaps.
goto is local withing the function, right? You can call these situations
"locally-handleable errors", too, if you like but they IMHO do not
require macros (no more than other business logic, that is). If your
desired control point is few call stacks up, goto can't help you and
this is a distinctive characteristic of an error to me.


>> People tend to misuse exceptions, that's true. But IMHO they misuse
>> other C++ features much more. For example they tend to misuse function
>> overloading. In particular operator overloads. As well as namespaces.
>> And passing by references. As well as name hiding. And especially
>> templates. And compile-time policies. And SFINAE. And recursive
>> template instatiations. Typelists in particular. And compiler time in
>> general. And even old poor preprocessor. And what not. And did I
>> mention operator overloading yet? Of the above misuses, misusing
>> exceptions looks a smaller sin to me.
>
> I think error management is the most important and the hardest to get right.
> It is both permeating and subsystem-ish whereas the other things are
> detail-ish.
It definitely is if you do not limit the scope of your effort first.
"Fixing the world" is rarely productive enterprise. So, the clear
definition of what is and, most importantly, what is not an error, is in
order as well as some definition of what you would expect from error
management.

-Pavel

== 2 of 5 ==
Date: Thurs, Nov 26 2009 8:00 pm
From: Ian Collins


paulto wrote:
> dragan wrote:
> [snipped]
>>> Quite a bit of code will you need to properly destroy automatic
>>> objects (which is quite often the required part of "error handling".
>>> If handling of an error does not require stepping way back, that
>>> error can be IMHO renamed to "yet another condition arising at normal
>>> course of given business").
>>
>> Another simple answer from moi: RAII. Problem solved. RAII and exceptions
>> are orthogonal concepts. RAII works as good with other error handling
>> strategies as it does with exceptions.

> RAII is a great idea but you need something to kick off the destructors.
> It may be an important component of error handling strategy but
> exception or something else is needed to actually kick off object
> destruction if error processing requires changing the context outside of
> normal flow control operation.

That's exactly what RAII does for you. You manage resources so they
will be freed when the managing object goes out of scope.

--
Ian Collins


== 3 of 5 ==
Date: Thurs, Nov 26 2009 8:37 pm
From: Pavel


Ian Collins wrote:
> paulto wrote:
>> dragan wrote:
>> [snipped]
>>>> Quite a bit of code will you need to properly destroy automatic
>>>> objects (which is quite often the required part of "error handling".
>>>> If handling of an error does not require stepping way back, that
>>>> error can be IMHO renamed to "yet another condition arising at normal
>>>> course of given business").
>>>
>>> Another simple answer from moi: RAII. Problem solved. RAII and
>>> exceptions
>>> are orthogonal concepts. RAII works as good with other error handling
>>> strategies as it does with exceptions.
>
>> RAII is a great idea but you need something to kick off the
>> destructors. It may be an important component of error handling
>> strategy but exception or something else is needed to actually kick
>> off object destruction if error processing requires changing the
>> context outside of normal flow control operation.
>
> That's exactly what RAII does for you. You manage resources so they will
> be freed when the managing object goes out of scope.
>
How do you make the language to realize the object is going out of scope
if you do not use exceptions? The discussion is about using exceptions
vs alternative error-processing techniques. As dragan correctly points
out, RAII is an orthogonal concept to the method of dispatching the
control point to the desired spot in the code (the concept that works
with exceptions quite nicely, BTW as many orthogonal concepts do). I am
not quite sure though why he mentioned it at all -- it only makes the
point in favor of exceptions as it seems to me.

-Pavel


== 4 of 5 ==
Date: Thurs, Nov 26 2009 9:18 pm
From: "dragan"


paulto wrote:
> dragan wrote:
> [snipped]
>>> Quite a bit of code will you need to properly destroy automatic
>>> objects (which is quite often the required part of "error handling".
>>> If handling of an error does not require stepping way back, that
>>> error can be IMHO renamed to "yet another condition arising at
>>> normal course of given business").
>>
>> Another simple answer from moi: RAII. Problem solved. RAII and
>> exceptions are orthogonal concepts. RAII works as good with other
>> error handling strategies as it does with exceptions.
> RAII is a great idea but you need something to kick off the
> destructors. It may be an important component of error handling
> strategy but exception or something else is needed to actually kick off
> object
> destruction if error processing requires changing the context outside
> of normal flow control operation.

Not really. Local objects will have their destructors called when they go
out of scope. That has nothing to do with exceptions, PER SE. Yes, if you
create a C++ exception mechanism, then you must, in turn, create a new way
for destructor calling. Otherwise though, destructors get called when the
object goes out of scope.

Is there a reason why there is so much pedantic and elementary discussion
necessary here? Personally, _I_ assume that everyone here knows everything
in anything ever written in a commonly available C++ book/programming book,
etc. Save for the "harder" stuff. While it is "fun" a little bit to "burn
things in" or "retrive data in the back of the mind", sometimes it appears
that some people in these language groups are just "chomping at the bit" for
an opportunity to recite common knowledge, at the expense of another maybe,
and for what? Is there some contest I don't know about? I felt the need to
"reprimand" and "take to the mat" the other guy for childish tactics for the
very same reason. This little passage is not to curb questions and thoughts
of those who trully don't know and seek to know: there is NO dumb question.
I mean, I remember when I didn't know everything and how it sucked so bad,
but I digress. :)

(Yes, when I say something that is incorrect, I'm just faking it: I really
do know. Yeah, that's the ticket!)

>
>>> Essentially to me it sounds like: I prefer not to mistake business
>>> requirements for errors.
>>
>> I just meant that I don't want to use the complex thing when another
>> simple thing will work just fine.
> see below..
>
>>
>>> And I could not agree with your more if
>>> that's what you mean. To me an error means: I can't continue this
>>> action. Now what am I going to do? At this point, to have at least
>>> the second choice (the first is to terminate the program and it does
>>> not require exceptions),
>>
>> Termination is only a choice in application code, not in library
>> code. A library has to propogate or handle the error. Maybe if a
>> precondition is violated you can make a case for termination from a
>> library, not sure.
> see below...
>
>>
>>> a robust context-switching mechanism is
>>> needed (longjmp/setjmp, EPOC32/Symbian's "Leaves" with home-made
>>> cleanup stack etc -- you name it).
>>
>> I wouldn't call setjmp/longjmp a "context switching mechanism", but
>> I know what you meant. setjmp/longjmp is not an option in C++
>> because destructors aren't called during "the unwinding" of the
>> "call stack".
> Exactly my point. It won't automatically, you will have to hand-craft
> some stupid

Ah, now we are getting "real". You say "stupid" and you meant it
passionately. OK, noted. There's nothing wrong with passion and/or
personality (as if "boring" language newsgroups didn't need help in that
department). :P

> mechanism like EPOC32/Symbian cleanup stack and never
> forget put your important objects on it. I am just saying: for error
> processing some mechanism of context-switching is needed (BTW
> longjmp/setjmp is context-switching: the context in this case are the
> registers including instruction pointer or equivalent and stack frame
> pointers or equivalents.

I would and do reserve that terminology for the commonly known usage of it:
switching from user mode to kernel mode, and switching threads too.

> In practice, it's not enough as you want
> application-level "unwinding" of automatic objects as you change the
> stack pointers or equivalents;

You don't have to do that if you aren't "setjmping/longjmping" or "C++
exceptioning": it happens just as in normal program flow. Destructors get
called when class objects go out of scope.

> that's why I am saying exceptions are
> convenient and cheap

You're are juxtaposing "cause and effect".

> without obvious drawbacks for the purpose (as
> long as you do not require more flexibility in selection of error
> processing code targets than exception give you), library-based
> cleanup-stack is worse and longjms/setjmp is still worse.. )

OK, this is turning into a tangent about "why you should use exceptions".
Save to say, you are "preaching to the choir". I don't want to age standing
still and this thread is becoming one of those rehashes of stuff everyone
already knows and makes their own choices about. Up next for sure: "why you
should use garbage collection". No offense, but I have better, more
important, more fun, <more other>, things to do. Unless you have some "new
twist" on the old material, I don't want to hear it again. No offense.

>
>>
>>> In most situations where the
>>> failed "action" is not a separate "task" (whatever this means -- a
>>> thread, a process or whatever -- in which case you could send a
>>> message to another task and terminate the failed task),
>>
>> Doesn't appear to be an option because that won't "unwind the stack".
> If you terminate the process, the automatic objects are destroyed;

While I don't not believe you, I don't believe you. I probably don't have to
know that either because:

1. It is probably platform-specific.
2. It's not a separate thing to design around the whole envelope of such
behavior.

> if
> the "task" is something else, you are right, it's on you again :-).
> That's again why I say exceptions are convenient.

"Convenience" is not even on the list of requirements though.

>
>>
>>> exceptions
>>> seem to be the most convenient and least costly (in terms of
>>> programming/code maintenance) mechanism.
>>
>> That's one way to do it, yes. I'm sure there are others, but that
>> necessarily commits you to using more than one EH thing.
> I mentioned few above; but don't know anything as convenient as
> exceptions.

"I gotta go".

>>>> Locally handle-able conditions (errors)
>>> This is telling.. what is you definition of an error as opposed to
>>> any other "locally handle-able" condition?
>>
>> I don't want to get into a glossary debate.
> I am not trying going there either; but we seem to be talking about
> different things when we mention "error" term and this is not
> productive.

I didn't see that as hampering the elementary and pendantic dialog, but I do
agree that a reasonably agreed-upon glossary of terms is required for
efficient discussion or debate or problem resolution. I think TOO much time
is spent discussing different things ("talking past each other") in these
language groups for that very reason: everyone starts jabbering in their own
foreign English/Technolang. Which is fine if it is clear from the context,
else it is very wasteful.

> I would suggest to exclude A "locably-handleable"
> conditions from the discussion.

There is no more discussion unless you have something new (to the larger
scope of the body of knowledge that is this stuff) to present.

> I do not see a reason for segregating
> them into a separate category of "errors" from other
> application-level conditions;

Well you ponder that some more if you want to. I consider classification of
errors an important step in error management. Without thought in that task,
I would assess the development process deficient. Nuff said. I'm not here to
talk about my development methods.

> you seem to argue exceptions is not the best way of processing them;

"best" sounds very final. Don't you think? It's a good way. A car may be
"the best way" to go to work, but I still ride my bike sometimes. Go figure!

> I
> do not challenge this at all, I just do not call these "business
> cases" or "uses cases" "errors".

I can't spend more time on this.

>
>>
>>>> are much more numerous than global errors handle-able appropriately
>>>> by a technique such as set_new_handler.
>>
>>> Again, how do you destroy C++ local objects with using a handler?
>>
>> Well, perhaps you can resume after the handler runs if that is how
>> your handler system works.
> See above paragraph this time :-).
>
>> If still no go, RAII time to do it's thing.
> So, how do you kick-off the destructors for objects you initialized
> under RAII paradigm?

"kick off" what? There's nothing to "kick off", unless you are under the
impression that "unwind" is something tied to an exception mechanism. Do you
know what an exception is? Is it different from an "error"? How? Have you
considered that someone like maybe Google who "shuns C++ exceptions" may
not be using ANY other kind of exception either? What is an "exception"? I
believe that answer will answer your questions about "kicking off
destructors".

>
>> How you
>> setup functions to do cleanup is a stylistic preference. A few
>> macros and a goto macro perhaps.
> goto is local withing the function, right?

Yes.

> You can call these
> situations "locally-handleable errors", too, if you like but they
> IMHO do not require macros (no more than other business logic, that is).

By now I'm "getting to know you", and "your take" on macros I'm sure can be
easily ascertained from "your take" on exceptions. No offense, but you are
repeating programming "cliches".

> If your
> desired control point is few call stacks up, goto can't help you and
> this is a distinctive characteristic of an error to me.

So why are you talking at me about it? Thought + time = resolution.

>
>
>>> People tend to misuse exceptions, that's true. But IMHO they misuse
>>> other C++ features much more. For example they tend to misuse
>>> function overloading. In particular operator overloads. As well as
>>> namespaces. And passing by references. As well as name hiding. And
>>> especially templates. And compile-time policies. And SFINAE. And
>>> recursive template instatiations. Typelists in particular. And
>>> compiler time in general. And even old poor preprocessor. And what
>>> not. And did I mention operator overloading yet? Of the above
>>> misuses, misusing exceptions looks a smaller sin to me.
>>
>> I think error management is the most important and the hardest to
>> get right. It is both permeating and subsystem-ish whereas the other
>> things are detail-ish.
> It definitely is if you do not limit the scope of your effort first.
> "Fixing the world" is rarely productive enterprise. So, the clear
> definition of what is and, most importantly, what is not an error, is
> in order as well as some definition of what you would expect from
> error management.

"I don't know what an error is". I want you to tell me. Unfortunately, I
have an idea of how long that will take until you know and I can't wait that
long. Don't ever again try to suck me into an elementary/pendantic
discussion about this stuff, thanks. When you have something new to add to
the existing "body of knowledge", I'll probably be reading it.


== 5 of 5 ==
Date: Thurs, Nov 26 2009 9:20 pm
From: "dragan"


Ian Collins wrote:
> paulto wrote:
>> dragan wrote:
>> [snipped]
>>>> Quite a bit of code will you need to properly destroy automatic
>>>> objects (which is quite often the required part of "error
>>>> handling". If handling of an error does not require stepping way
>>>> back, that error can be IMHO renamed to "yet another condition
>>>> arising at normal course of given business").
>>>
>>> Another simple answer from moi: RAII. Problem solved. RAII and
>>> exceptions are orthogonal concepts. RAII works as good with other
>>> error handling strategies as it does with exceptions.
>
>> RAII is a great idea but you need something to kick off the
>> destructors. It may be an important component of error handling
>> strategy but exception or something else is needed to actually kick
>> off object destruction if error processing requires changing the
>> context outside of normal flow control operation.
>
> That's exactly what RAII does for you. You manage resources so they
> will be freed when the managing object goes out of scope.

That's all I had to say? I just spent a half hour replying to him. Twas time
well-spent though. I don't regret it at all. (OK, I do, but for selfish/time
reasons).

==============================================================================
TOPIC: Portability and marshalling integral data
http://groups.google.com/group/comp.lang.c++/t/d7831b8e84cbb8c3?hl=en
==============================================================================

== 1 of 1 ==
Date: Thurs, Nov 26 2009 8:17 pm
From: "dragan"


James Kanze wrote:
> On Nov 25, 11:09 pm, "dragan" <spambus...@prodigy.net> wrote:
>> James Kanze wrote:
>>> On Nov 25, 11:45 am, "dragan" <spambus...@prodigy.net> wrote:
>
> [...]
>>>> There is more than just endianness to consider, of course.
>>>> You have to maintain the spec with what you send out by
>>>> controlling it with whatever you have to, like compiler
>>>> pragmas to control alignment and padding.
>
>>> You typically can't control it enough just by flipping a few
>>> compiler switches.
>
>> If you write the spec to assume the conventions of the
>> platform the software was written on, then you can.
>
> If you write the spec to assume the conventions of the platform
> you're working on, you may not have to flip any switches.

Well let's not be TOO lazy now. There is a line of practicality apart from
the EXTREMES.

> But
> of course, your code won't be portable; it won't implement the
> same spec on a different platform.

The research needs to be done. "Blind faith" is never an option (unless it's
a homework assignment and you have more important classes to worry about).

>
> Historically, this mistake was made a lot in the early days of
> networking. XDR, for example, follows exactly the conventions
> of the Motorola 68000, and until fairly recently, you could just
> memory dump data from a 32 bit Sparc, and it would be conform
> to the protocol. (I think more modern Sparc's require 8 byte
> alignment of double, whereas the protocol only requires 4 byte
> alignment.) Of course, if you're on an Intel platform, you'll
> need some extra work. (This works against Brian's idea, since
> most servers are still big-endian, where as Intel dominates
> the client side overwhelmingly.)

Knowing that, you then shouldn't have "suggested" to "make the platform the
spec", something I never implied whatsoever but that you chose to take to
the extreme.

>
>> Flip a few switches and whatever comes out is to spec. Call it
>> "an implicit specification" then. Then, the high-level spec
>> is: little endian, integer sizes, no padding, all integer data
>> on natural boundaries. Anything else anyone wants to know will
>> be specified later. :)
>
> 2's complement as well, of course:-).

I don't remember. I go back and read about that stuff time and again, and
time and again it never sticks in my mind, not like the easy-to-remember
endian/padding/alignment things. So yes, maybe, I'm not sure. Certainly
something to decide before deployment of a protocol though. I'd settle for
the "80%" solution way before I'd go to the OTHER EXTREME of trying to be
platform-agnostic.

>
> Lucky for us today, none of the people designing protocols were
> on Unisys platforms:-). (In fact, most of the early work on IP
> and TCP was done on DEC platforms. And the byte oriented DECs
> are little endian.

Really? Then why did they choose big-endian as the wire endian-ness?

> But I think when the work was being done, it
> was still largely DEC 10's: word addressed, with 36 bit words,
> and by convention, 5 seven bit bytes in each word, with one left
> over bit. At least they didn't base the protocol on that.)
>
>> Of course, nothing need to be specified if developer B is
>> using the same platform (compiler, os, hardware).
>
> Nothing needs to be specified if you can guarantee that for all
> time, all future developers will be using the same platform
> (compiler, including version, os, hardware). As soon as you
> admit that some future version might be compiled with a later
> version of the compiler, you're running a risk.

That is understood. No risk, no gain. :)

> (Note that the
> byte order in a long changed from one version to the next in
> Microsoft compilers for Intel. And the size of a long depends
> on a compiler switch with most Unix systems.)

What's "a long"?? ;) I only recognize well-defined integer types. Not some
nebulous language specification vaguery. :)

==============================================================================
TOPIC: How to get an insertion hint for an unordered associated container?
http://groups.google.com/group/comp.lang.c++/t/21e47512ffcaf8a2?hl=en
==============================================================================

== 1 of 1 ==
Date: Thurs, Nov 26 2009 8:30 pm
From: Pavel


James Kanze wrote:
> On Nov 24, 5:24 am, Pavel
> <pauldontspamt...@removeyourself.dontspam.yahoo> wrote:
>> James Kanze wrote:
>>> On Nov 21, 8:34 pm, Pavel
>
> [...]
>>> rather than find, and using the return value as a
>>> hint---this does cost an extra comparison in your code,
>>> however. The cost of the second look-up in an unordered
>>> container cannot easily be avoided, but it is O(1), and not
>>> O(lg n). The main potentially avoidable cost would be
>>> calculating the hash code twice, but I don't think that the
>>> interfaces currently available have any provision to support
>>> this.
>
>> That is actually avoidable in tr1/unordered map (you can
>> access bucket(const key_type&) etc). However, O(1) (on
>> average, worst case is linear), is not 1. In my domain area,
>> spending 2*O(1) instead of O(1) often means "you won, I lost".
>> So, I am trying to get to O(1) from 2 * O(1). If one assumes
>> that the lookup algorithm in hash is always like this:
>
>> 1. Identify the bucket.
>> 2. Linearly search in the bucket for the equal key or free spot or
>> end-of-bucket.
>
> I'm not sure that the (upcoming) standard requires linear search
> in the bucket, but it does require buckets, which are accessible
> for some things (but I'm not sure what) from the user interface.
> I think that the available functionality is only sufficient for
> instrumentation---determining how effective your hash function
> actually is.
>
>> (which it is in my version of GNU implementation of tr1
>> unordered_map). I could even say my problem if solved (if
>> only they used the hint, which they don't as you correctly
>> suggested). But it is not guaranteed.
>
> The "hint" is in the form of an iterator. I'm not sure how they
> could use it.
>
> It might be useful if they provided functions for looking up and
> inserting into a given bucket (at your own risk, of course);
> you could then call c.bucket(key) (which calculates the hash
> code), and do all further operations on the returned bucket.
> Probably a bit too dangerous, however.
>
>>> (Basically, it would mean> calculating the hash value in
>>> user code, and having additional variants of functions like
>>> find and insert which take a pre-calculated hash value.)
>
>>> IIRC, the unordered containers do have variants of insert which
>>> take a "hint", but this is only present for compatibility with
>>> the existing ordered containers; the hint is not used.
>
>> Just noticed that.. Don't understand why they don't use it:
>
> Because it's an iterator, and an iterator doesn't contain any
> useful information to use in the case of an unordered container.
>
>> they have to re-compute same information in insert() again (at
>> least bucket index and hash code). I hope they will use it in
>> the future though and that API is there to allow optimization,
>> not just for compatibility..
>
> Explain how? The iterator doesn't contain the hash code in any
> way.
Iterator may contain anything that addresses the element, in particular
hash_code (it does so in one version of GCC hashtable, more precisely,
points to the node that contains hash_code). It has to contain something
to allow navigation (++, --). For example, it could contain:
1. A handle for constant-time access to the bucket, to be able to find
out where the bucket ends (like an index of the bucket in some
array/vector/deque or a pointer to it),
2. A handle for constant-time access to element in the bucket (another
index or whatever)
3. A handle for constant-time access to the container (to know how to
navigate to the next bucket as you need for ++, --). Again, a pointer or
similar.

If buckets contain pointers to actual objects (which sounds feasible as
the Standard guarantees the references and pointers to the objects are
not invalidated during re-hashes), the above is quite enough to insert
the object "at" given iterator or at first available space in the bucket
pointed to by the iterator.


>
> Most of the hash maps I've written in the past would cache the
> last element found, in order to support things like:
>
> if ( m.contains(x) ) {
> m[x] = 2*m[x] ; // or whatever...
> }
I understand you can optimize the set for the usage pattern you think is
common. This comes at cost even for this use, however, as the
comparision may be much more expensive than hash-function computation
and you guarantee you will have an extra comparison in m[x] at all
times. We know we can do without (see above) so why should we live with it.

>
> efficiently. It still required a comparison for each access, in
> order to know whether I could use the cached value, but it did
> avoid multiple calculations of the hash code when accessing the
> same element several times in succession.
You are making assumptions that may be very true for your particular
problem but I would not use these in a general-purpose library like STL.

>
>> But the equal_range() definition to return two end() iterators
>> on "not found" condition is a hog -- I can't understand why
>> this could not be defined as "return an empty range" so either
>> of two identical iterators that could be used as a hint for
>> insertion, consistent with how it's defined for ordered ass.
>> containers.
>
> What does "consistent with how it's defined for ordered
> containers" mean here? The value returned from lower_range
> defines where any new element should be inserted, according to
> the ordering relationship. In an unordered container, there is
> no specific place where the new element should be inserted.
> What you're asking for really isn't possible.
Why not? You can have a bucket and an index in the bucket and the bucket
has the index if the last element. If a pointer to the element stored
the bucket (think of the bucket as an array/vector of pointers although
it does not have to be it) is NULL, insert your element into this spot;
otherwise, if the bucket has free space insert it at the end of the
bucket; otherwise, you have to re-hash (but you would have anyway;
supposedly, you still have "amortized constant" for the average
insertion time)

>
>> What is the benefit of requiring them both be end()? Checking
>> for "not found" condition costs one iterator comparison either
>> way.. seems like waste to me.
>
> No benefit, perhaps, but no real harm either. Ordered and
> unordered containers are fundamentally different beasts.
If you returned two identical iterators pointing to a free spot in the
correct bucket (say the first free spot), you would know to insert your
element there without any computations whatsoever.

> If you're concerned about the time necessary to calculate the
> hash function, you could use a wrapper for the key, which caches
> the hash function once it has been calculated, and uses the
> cached value if it is present. Most of the time, I suspect that
> it won't make a difference (although for strings, if the keys
> can be fairly long, maybe). So you end up with something like:
>
> class CachedHashString : private std::string
> {
> bool isHashed;
> unsigned hashValue;
> public:
> // Duplicate any needed constructors, setting isHashed
> // to false.
>
> // using declarations for whatever functions you want
> // to expose (only const!)
> unsigned hash() const
> {
> if ( ! isHashed ) {
> hashValue = ... ;
> isHashed = true;
> }
> return hashValue;
> }
> };
>
> and the hash function you use with the container uses the member
> hash function.
I know.. but as per above, I do not think this is necessary. The cost of
insertion can be anything -- in case of conflict it may even be some
secondary hash or linear or non-linear search in the overflow area or
similar. The Standard does not define how exactly the overflows are
processed.

To summarize my point:

The Standard recognizes the hint may be useful (it is still in the API
for unordered ass. containers) and I am ok that GCC STL does not use it
now -- it or another implementation may do it in the future or I can
write it myself and the client code will continue to rely on the
Standard-compliant unordered ass. container while enjoying the faster
implementation.

But, I do have an issue with the requirement to return two end()
iterators in equal_range() on "not found" condition instead of such a
hint. I think it is a defect in the Standard that limits possible
optimizations without good reason.

>
> --
> James Kanze


==============================================================================
TOPIC: Why do some code bases don't use exceptions?
http://groups.google.com/group/comp.lang.c++/t/c255001068888229?hl=en
==============================================================================

== 1 of 5 ==
Date: Thurs, Nov 26 2009 9:35 pm
From: "dragan"


Vladimir Jovic wrote:
> dragan wrote:
>> peter koch wrote:
>>> On 25 Nov., 12:14, "dragan" <spambus...@prodigy.net> wrote:
>>>> peter koch wrote:
>>>>> On 24 Nov., 10:48, James Kanze <james.ka...@gmail.com> wrote:
>>>>> When not using exceptions, you more or less write the hidden
>>>>> error- returning path explicitly in your code. In my experience,
>>>>> this often gives a signicifand increase in source-code size
>>>> Can you give some numbers?
>>> Not any exact ones, but I have been working in places where
>>> exceptions were not used (due to some code being quite old and no
>>> one caring about fixing). Code there typically looked something
>>> like: int func(parm p,std::string &result)
>>> {
>>> std::string s;
>>> int error;
>>>
>>> result = func_1(parm,s);
>>> if (error != OK)
>>> {
>>> return error;
>>> }
>>> error = func_2(s);
>>> if (error != OK)
>>> {
>>> return error;
>>> }
>>> result = s;
>>> return OK;
>>> }
>>>
>>
>> #define ERROR (-1)
>> #define OK (0)
>>
>> #define Try(x) if(x != OK) goto unwind;
>> #define CatchAll unwind:
>>
>> // Not the same function as you have cuz I
>> // don't want to figure out what you were
>> // doing hypothetically. Adequate for illustration.
>> // Many variations on the below theme exist
>> // including masking of setjmp/longjmp etc.
>> //
>> int func (parm p)
>> {
>> std::string s;
>> Try(func_1(p, s))
>> Try(func_2(s))
>> return OK;
>>
>> CatchAll
>> // do cleanup, rollback, recovery, etc. as appropriate
>> return ERROR;
>> }
>>
>
> A function (or a method) has to have the same crap. This remind more
> of C, then C++.
>
> btw take a look at this:
> http://www.google.com/search?q=macros+are+evil&btnG=Search+the+C%2B%2B+FAQ&sitesearch=www.parashift.com
>
> Once you really try exceptions, you will laugh at this example.

Once you study the realm that C++ exceptions fall under, you will be
enlightened. It's fine and dandy to just accept things thrown at you in the
form that they are thrown at you. If you are "that kind" though, I wouldn't
want you on my development "team". (You betcha I knew people where going to
drive their cadillacs into that "example" I gave. Have you been "had"?)


== 2 of 5 ==
Date: Thurs, Nov 26 2009 9:31 pm
From: "dragan"


Paavo Helde wrote:
> "dragan" <spambuster@prodigy.net> wrote in
> news:gXkPm.25025$kY2.2653@newsfe01.iad:
>
>> peter koch wrote:
>>> On 25 Nov., 12:14, "dragan" <spambus...@prodigy.net> wrote:
>>>> peter koch wrote:
>>>>> On 24 Nov., 10:48, James Kanze <james.ka...@gmail.com> wrote:
>>>>
>>>>> When not using exceptions, you more or less write the hidden
>>>>> error- returning path explicitly in your code. In my experience,
>>>>> this often gives a signicifand increase in source-code size
>>>>
>>>> Can you give some numbers?
>>>
>>> Not any exact ones, but I have been working in places where
>>> exceptions were not used (due to some code being quite old and no
>>> one caring about fixing). Code there typically looked something
>>> like:
>>>
>>> int func(parm p,std::string &result)
>>> {
>>> std::string s;
>>> int error;
>>>
>>> result = func_1(parm,s);
>>> if (error != OK)
>>> {
>>> return error;
>>> }
>>> error = func_2(s);
>>> if (error != OK)
>>> {
>>> return error;
>>> }
>>> result = s;
>>> return OK;
>>> }
>>>
>>
>> #define ERROR (-1)
>> #define OK (0)
>
> If you are happy writing the above two lines, it shows clearly IMO
> that you have never done any large scale development in C++.
> Consequence: you have no idea what you are talking about when ranting
> about exceptions. No offense, I just want to put things in a more
> correct perspective.

That you thought that I proposed that as an alternative to anything shows
that you are a greenbean, wet behind the ears. :P I'm not here to divulge
proprietary or patentable technology. Deal with it little boy. Cry me a
river because I won't give you my source code. BTW, your mommie called me to
tell you to: GET A CLUE!


== 3 of 5 ==
Date: Thurs, Nov 26 2009 9:36 pm
From: "dragan"


Vladimir Jovic wrote:
> Vladimir Jovic wrote:
>> dragan wrote:
>>> peter koch wrote:
>>>> On 25 Nov., 12:14, "dragan" <spambus...@prodigy.net> wrote:
>>>>> peter koch wrote:
>>>>>> On 24 Nov., 10:48, James Kanze <james.ka...@gmail.com> wrote:
>>>>>> When not using exceptions, you more or less write the hidden
>>>>>> error- returning path explicitly in your code. In my experience,
>>>>>> this often gives a signicifand increase in source-code size
>>>>> Can you give some numbers?
>>>> Not any exact ones, but I have been working in places where
>>>> exceptions were not used (due to some code being quite old and no
>>>> one caring about fixing). Code there typically looked something
>>>> like: int func(parm p,std::string &result)
>>>> {
>>>> std::string s;
>>>> int error;
>>>>
>>>> result = func_1(parm,s);
>>>> if (error != OK)
>>>> {
>>>> return error;
>>>> }
>>>> error = func_2(s);
>>>> if (error != OK)
>>>> {
>>>> return error;
>>>> }
>>>> result = s;
>>>> return OK;
>>>> }
>>>>
>>>
>>> #define ERROR (-1)
>>> #define OK (0)
>>>
>>> #define Try(x) if(x != OK) goto unwind;
>>> #define CatchAll unwind:
>>>
>>> // Not the same function as you have cuz I
>>> // don't want to figure out what you were
>>> // doing hypothetically. Adequate for illustration.
>>> // Many variations on the below theme exist
>>> // including masking of setjmp/longjmp etc.
>>> //
>>> int func (parm p)
>>> {
>>> std::string s;
>>> Try(func_1(p, s))
>>> Try(func_2(s))
>>> return OK;
>>>
>>> CatchAll
>>> // do cleanup, rollback, recovery, etc. as appropriate
>>> return ERROR;
>>> }
>>>
>>
>> A function (or a method) has to have the same crap. This remind more
>> of C, then C++.
>
> Off course, this should have been:
>
> A function (or a method) *that is using this function* has to have the
> same crap. This remind more of C, then C++.

"you have some redeeming quality" in that you recognize history. :/ <-- can
anyone parse this?


== 4 of 5 ==
Date: Thurs, Nov 26 2009 9:47 pm
From: "dragan"


peter koch wrote:
> On 26 Nov., 02:35, "dragan" <spambus...@prodigy.net> wrote:
>> peter koch wrote:
>>> On 25 Nov., 12:14, "dragan" <spambus...@prodigy.net> wrote:
>>>> peter koch wrote:
>>>>> On 24 Nov., 10:48, James Kanze <james.ka...@gmail.com> wrote:
>>
>>>>> When not using exceptions, you more or less write the hidden
>>>>> error- returning path explicitly in your code. In my experience,
>>>>> this often gives a signicifand increase in source-code size
>>
>>>> Can you give some numbers?
>>
>>> Not any exact ones, but I have been working in places where
>>> exceptions were not used (due to some code being quite old and no
>>> one caring about fixing). Code there typically looked something
>>> like:
>>
>>> int func(parm p,std::string &result)
>>> {
>>> std::string s;
>>> int error;
>>
>>> result = func_1(parm,s);
>>> if (error != OK)
>>> {
>>> return error;
>>> }
>>> error = func_2(s);
>>> if (error != OK)
>>> {
>>> return error;
>>> }
>>> result = s;
>>> return OK;
>>> }
>>
>> #define ERROR (-1)
>> #define OK (0)
>>
>> #define Try(x) if(x != OK) goto unwind;
>> #define CatchAll unwind:
>>
>> // Not the same function as you have cuz I
>> // don't want to figure out what you were
>> // doing hypothetically. Adequate for illustration.
>> // Many variations on the below theme exist
>> // including masking of setjmp/longjmp etc.
>> //
>> int func (parm p)
>> {
>> std::string s;
>> Try(func_1(p, s))
>> Try(func_2(s))
>> return OK;
>>
>> CatchAll
>> // do cleanup, rollback, recovery, etc. as appropriate
>> return ERROR;
>>
>> }
>>
>> Macros are your friend to make the language conform to YOUR
>> preferences! :)
>>
>
> You just gave a perfect example

It wasn't an example.

> of how to make bad code worse.

Or how to make people THINK? I mean, you're thinking about it, right?
Success.

> Your
> code has several issues:
>
> 1) You fail to "return" the result when everything goes well.

?? You can't see the "return OK;" statement??

> 2) You fail to return the error-code when things go wrong.

?? You can't see the "return ERROR;" statement?

You "got me": I had to stick in the baggage from the previous poster's
example: std::string. Touche, and: :P. If you were REALLY smart though,
you'd ask, "why is this dude who is avoiding exceptions using
std::string??!". Answer: he wouldn't.

> 3) Your code has reintroduced the hidden paths you dislike about
> exceptions.
>
> All this for reducing a function from ten lines to 6 (generously not
> counting your macros) compared to the exception-enabled oneliner.
>
> Finally, your system is quite fragile - forbidding its use in some
> cases. Change the function slightly, and it becomes ill-formed:
>
> int func (parm p)
> {
> std::string s1;
> Try(func_1(p, s1)) // Ill-formed!
> std::string s2;
> Try(func_2(s2))
> return OK;
>
>
> CatchAll
> // do cleanup, rollback, recovery, etc. as appropriate
> return ERROR;
> }
>
> So your macro-voodoo not only introduces hidden return-paths. It also
> prevents writing idiomatic C++ (if that was not already lost) and
> increases the code-size considerably.

If you like Humvees, but they only were available in pink, maybe you'd
repaint it? Some people would just buy something else. Oh, there IS NOTHING
ELSE you say? Don't be so sure. Is that a corporate Vee you're driving?
Dude, nice COLOR! (hehehe).


== 5 of 5 ==
Date: Thurs, Nov 26 2009 10:28 pm
From: "dragan"


James Kanze wrote:
> On Nov 26, 1:44 am, "dragan" <spambus...@prodigy.net> wrote:
>> James Kanze wrote:
>>> On Nov 25, 11:03 am, "dragan" <spambus...@prodigy.net> wrote:
>>>> James Kanze wrote:
>>>>> On Nov 23, 8:09 pm, "io_x" <a...@b.c.invalid> wrote:
>>>>>> "dragan" ha scritto nel
>
> [....]
>>>>> That's the whole point of exceptions. They're for the sort of
>>>>> problems where it doesn't matter where the problem occured; the
>>>>> handling is the same. If you run out of memory processing a
>>>>> request, for example, it doesn't matter where you were in the
>>>>> processing when you ran out; you just abort the request (but not
>>>>> the process) with an error message, and continue.
>
>>>> You seem to be big on aborting.
>
>>> Attention about word use. There's aborting (in the sense of
>>> calling abort()), and aborting (in the more general sense,
>>> of immediately terminating some action that you were in the
>>> process of doing). In this case, I'm using the other sense:
>>> say you've received a request on your LDAP server, and you
>>> run out of memory trying to service it (because it requires
>>> interpreting some obscenely complicated filter expression,
>>> for example). When you detect the lack of memory, you're
>>> down in some really deap parsing function, executing
>>> operator new. You (or rather the system) raises an
>>> std::bad_alloc exception, which you catch at the top level,
>>> and abort the request (not the program), returning an error
>>> message of "insufficient resources", or the like.
>
>> Ah. Bad choice of word then to describe that.
>
> I didn't invent the language (English). I just use it.

Don't worry about. It's my "second language", but maybe that elicited me to
study it more. I have found no error in you use of English.

> I don't
> know of any other word for what I described; abort is the
> standard word.

It sounds like an "unstudied appropriation". "Hurried". Inappropriate and
incorrect.

>
>> I think most people who see "abort" think exit the process or
>> terminate the thread.
>
> I think most people read more than just a word at a time,

Oh, you know I'm not gonna let you off that easy Mr. (Did you read where I
was spanking the other with such childish tactic? Did he maybe LEARN it from
you??!)

> and
> the expression "abort the request" is quite clear. "Abort the
> request" is not "abort the process".

Noted: your vocabulary is terse so you requisition what you have at your
disposal, hoping that it will be understood (or hoping it will give you a
scapegoat!). I understand the way you think. You are unsure of what to do.
And so, unsure of yourself. But, you KNOW that you can be MORE or "the
bomb". Let's get it done. You're really Elvis, right? I mean really, you
can't hide forever right? Surely you are Elvis. The King!

:/ <-- parse this.

>
>> Even in your example above though, I wouldn't expect abort to
>> occur unless the situation has been going on for some time.
>> The server should have preallocated some resources for use in
>> such situations.
>
> I'm not sure I follow. The server will certainly have some
> resources preallocated, so that it can successfully log the
> error, unwind the stack, and return an error message.

Pfft. Stop already. To cut the convo short: I think I can deploy without C++
exceptions. Any of this "large scale" bullshit, does not apply to me, so
curb it already. Stop being pedantic. (Or not, it's all good: it's my fault
if I get sucked into these USELESS tiradal "discussions").

> But by
> definition, it can't use those resources for parsing the
> request, or they won't be available for the things they were
> reserved for.

Answer: too abstract. I have a real application and don't need to be
thinking about "THE general solution" that will do this that AND cure cancer
as a side effect. Nuff said. If you don't grok that, I don't care, you're
not my problem.

>
>>>> A very valid pattern is fixing the problem and resuming.
>
>>> If that's a valid reaction to the error, aborting isn't the
>>> answer. If the error was a coding error, you can't fix the
>>> source, recompile the code, and resume, so you abort. If
>>> the error was insufficient memory due to an overly
>>> complicated request, you can't simplify the request and
>>> resume: you abort the operation. (On receiving an
>>> "insufficient resources" error, of course, the client may
>>> try a simpler request.)
>
>>>> Some version of Windows expands the stack that way: a
>>>> violation occurs when trying to push beyond the current
>>>> stack frame and the system catches the error, expands the
>>>> stack by 4k and continues processing.
>
>>> (Isn't that how most systems work?
>
>> I don't know.
>
>>> That's more or less the way the old Berkley kernel worked on
>>> Sun 3's, and IIRC, PDP-11's memory manager unit was designed
>>> expressedly to support something like this, back in the days
>>> before virtual memory.)
>
>>> I'm not too sure how that's relevant to user code, however.
>>> Are you saying that if you get std::bad_alloc, you should
>>> try to get more memory?
>
>> See my comment above.
>
> Which one? Are you saying that if you get std::bad_alloc, you
> should output a message to the terminal, asking the sysop to
> insert additional memory chips, and only continue when he does?

I could call you facetious, but I think you trully are not following the
main points. Your scapegoat is that you follow too many threads. I said
"preallocate", but just like I said that error handling (not "management"
this time) is application-specific, so is that one specific error. I know
those answers. I don't want to entertain discussion or be the bouncing board
for those who only "read the books". No offense, but it's not my thing. And
no, I'm not being "high and mighty", nor am I about to be a whimp. (speaking
of whimps, I noticed you didn't have anything more to say about being WRONG
about "error reporting"). :) :P

>
>>> Frankly, out of memory is a special case, and most of the
>>> programs I've worked on installed a new_handler to abort in
>>> such cases. Not all, however, and particularly on
>>> transaction based systems where transactions can require a
>>> lot of memory, it often makes sense to just abort the
>>> transation. I can't think of much else you could do: call
>>> some system routine to create more virtual memory?
>
>> Preallocate for use in those times. Could be from an entirely
>> different heap or something. Or hardware even: a mem card in a
>> PCI-X slot ... possibilities are endless. EH is
>> application-specific.
>
> Preallocate what?

M-E-M-O-R-Y.

> Parsing an LDAP request requires unbounded

You don't really expect me graft my discussion on your post-conceived
scenario, do you? That would be so "unsporting".

> memory, since the request can be arbitrarily complicated: the
> filter expression can contain any number of parenthesized
> sub-expressions. It's just like a C or a C++ compiler: feed it
> a file with a function which contains 2 billion nested
> parentheses, and see what happens. You can't predict up front
> how complex an expression will be, and how much memory you'll
> need. Either you arbitrarily limit the complexity (for example,
> to prevent stack overflow if you're using recursive descent), or
> you handle insufficient memory. Or both: you might normally be
> able to handle the expression, but not if a thousand or so
> clients send it at the same time.

So, maybe "call me" when you have a PRODUCT like SmartHeap? Else maybe "shut
up"? You don't really think I'd consider hiring you before I'd buy a product
like that, do you? I do it differently, yes. Internally I DO "compete" with
the commercial memory allocator offerings. No offense meant.

Dragan
"English is my second language" :)

==============================================================================
TOPIC: Multiple inheritance and pointer equivalence
http://groups.google.com/group/comp.lang.c++/t/6ce10e4cd7c07869?hl=en
==============================================================================

== 1 of 1 ==
Date: Thurs, Nov 26 2009 11:58 pm
From: "io_x"

"Danny Woods" <dannywoodz@yahoo.co.uk> ha scritto nel messaggio
news:50skccrsex.fsf@gmail.com...
>
> Hi all,
>
> Given this simple program:
>
> ----
>
> #include <cstdio>
>
> class A { public: virtual ~A() {} };
> class B { public: virtual ~B() {} };
> class C : public A, public B { public: virtual ~C() {} };
>
> int main(void)
> {
> C *c = new C();
> A *a = c;
> B *b = c;
>
> printf("c: %p; a: %p; b: %p\n", c, a, b);
>
> delete c;
> return 0;
> }
>
> ----
>
> Is it to be expected that the addresses stored in a and b are different?
> I've tried this with Visual C++ and Cygwin g++, with identical results.
>
> The problem I have is that there are other subclasses of A and B that
> are distinct, but that there's a special case where the combined
> subclass, C, is required to fill both roles. When the code that cleans
> up a and b runs later, I'll end up with double deletion unless I can

i not find in the example above no double free;
where is it?

Can i use "this" inside the distructor function?

------------------------------
#include <stdio.h>
#include <stdlib.h>
#define P printf
#define i8 signed char

class A{
public:
A(){ Aarr= (i8*) malloc(1024); }
virtual ~A()
{P("~A(); this=%p\n", this);
free(Aarr);
Aarr= (i8*) -1;
}
i8* Aarr;
};

class B{
public:
B(){ Barr= (i8*) malloc(1024); }
virtual ~B()
{P("~B(); this=%p\n", this);
free(Barr);
Barr= (i8*) -1;
}
i8* Barr;
};

class C : public A, public B{
public:
virtual ~C(){ P("~C(); this=%p\n", this); }
};

int main(void)
{ C *c = new C;
A *a = c;
B *b = c;

if(c->Aarr==0||c->Barr==0)
{P("No memory\n");
goto end;
}
printf("c: %p; a: %p; b: %p\n", c, a, b);
end:;
delete c;
P("END\n");
return 0;
}

------------------------------------
c: 00852FD4; a: 00852FD4; b: 00852FDC
~C(); this=00852FD4
~B(); this=00852FDC
~A(); this=00852FD4
END

> reliably tell that a and b point to the same object, but the simple
> 'a == b' doesn't work here.
>
> Cheers,
> Danny.

==============================================================================

You received this message because you are subscribed to the Google Groups "comp.lang.c++"
group.

To post to this group, visit http://groups.google.com/group/comp.lang.c++?hl=en

To unsubscribe from this group, send email to comp.lang.c+++unsubscribe@googlegroups.com

To change the way you get mail from this group, visit:
http://groups.google.com/group/comp.lang.c++/subscribe?hl=en

To report abuse, send email explaining the problem to abuse@googlegroups.com

==============================================================================
Google Groups: http://groups.google.com/?hl=en

No comments: