Forums

Digression on Iterators

Started by Jon Kirwan October 18, 2011
On 16/06/12 21:49, Jon Kirwan wrote:
> On Sat, 16 Jun 2012 16:07:26 +0200, you wrote:
>
> >
> >I don't know, I'm afraid. I haven't used C++ very much as yet, and it
> >has always been with exceptions fully disabled ("-fno-exceptions in
> >gcc). Exceptions can be useful in some sorts of programming, but I
> >don't see them as a useful thing in embedded programming - and they can
> >be /very/ costly, in several different senses.
>
> I agree about the disabling of exceptions and exception
> handling -- except in some cases. I actually had to add a per
> thread, exception handler system (tethered into my operating
> system data structures) in one case, as it was the best way
> to support the customer's needs for maintainable code in a
> rather complex system. It helped a lot. This was in C but it
> supported all the usual nested TRY blocks and features most
> are used to and it kept completely separated systems for each
> thread.
>
> So there is no absolute, bright line in life. Just rules of
> thumb. The ability to use noexcept in C++ may actually be a
> bit of a boon for embedded use. Though I wouldn't know until
> I tested it out and looked at the resulting code.
>
> Jon
>

I am not sure if noexcept will negate all the bad points about
exceptions - you'd have to be consistent about using it everywhere, in
which case it is easier just to disable exceptions entirely (I would be
surprised if there were any embedded C++ compilers that don't have a
flag for disabling exceptions).

The main problem with exceptions is the obvious one - it makes it very
difficult to guess the control flow of the program. You can get
unexpected jumps at odd times, and you have to be /extremely/ rigorous
and structured in your programming to be sure you have full control.
With half that discipline you can get the same benefits from passing
error conditions and checking return values in the traditional C manner,
and having it clearly and explicitly shown in the code.

The secondary issue, that is particularly relevant in embedded systems
where code size and speed is often important, is that exceptions can
cripple your optimiser, and generate larger and slower code. At
multiple points in the generated code, the compiler has to add code to
deal with exceptions - for every function call that might throw an
exception (including every function whose definition is not known and is
not declared with noexcept), the compiler has to assume that an
exception will be thrown. That means stack unwinding, destructors being
called, etc. This can mean lots of overhead in code space and stack
space, the compiler's optimiser is hindered in re-ordering code, common
subexpression optimisations, etc.

mvh.,

David

Beginning Microcontrollers with the MSP430

On Sat, 16 Jun 2012 23:11:29 +0200, you wrote:

>I am not sure if noexcept will negate all the bad points about
>exceptions

I never speak in absolutes -- except when saying that I
absolutely don't do so. :)

I hope I didn't imply that noexcept would negate _all_ bad
points. I just thought it was a potentially useful addition
for some circumstances. It seems attractive, in that I
believe it may inform the compiler that it does NOT need to
generate exception handlers in code that doesn't specify any,
just to handle destruction of an object that _might_ need
destruction if some call to a function might cause an
exception.

Code that looks like:

.
.
.
x();
string y;
x();
.
.
.

Assume this resides in a module (file) where it looks exactly
like C (no exceptions, no try blocks, no use of exceptions,
etc.) and the only thing in all the code is that in ONE place
it specifies the construction of an object (y) that must be
destroyed if x(), which we will assume for now resides in a
different module where the source code is NOT visible to the
compiler, generates a throw. The first call to x() doesn't
need to trap anything, as there is nothing prior needing
destruction. The second call to x() does need such a hidden
mechanism because C++ is forced to deal with destroying y if
such an exception were to take place. And it doesn't know,
since it can't see the code for x(). I was hoping noexcept
would permit me to inform the compiler that it doesn't need
to worry so it can produce the same code for both calls to
x() (or, another way of saying it, it doesn't need to insert
exception handling to destroy y in the case of a throw but
only needs to destroy y in a non-exception context of the
current code.)

That's not much of an improvement. But it is an improvement
that might open an option, which would otherwise be closed to
me.

>- you'd have to be consistent about using it everywhere, in
>which case it is easier just to disable exceptions entirely (I would be
>surprised if there were any embedded C++ compilers that don't have a
>flag for disabling exceptions).

Here, I simply think you continue to speak in extremes. I am
speaking entirely in moderation. It is not the case that
either I want exceptions everywhere or else I want them
nowhere. That is extreme-minded mentality operating. Not
nuanced thinking.

There are cases where it would be important to me in some
places in an application that I am absolutely certain that
the burden of exception handling isn't being generated but
where elsewhere in the application such handling would be
fine.

In any case, more control is better in my mind. Gives me more
options, not fewer. The way you talk, you don't want options
but want only BLACK and WHITE thinking processes.

I'm not like that.

>The main problem with exceptions is the obvious one - it makes it very
>difficult to guess the control flow of the program. You can get
>unexpected jumps at odd times, and you have to be /extremely/ rigorous
>and structured in your programming to be sure you have full control.
>With half that discipline you can get the same benefits from passing
>error conditions and checking return values in the traditional C manner,
>and having it clearly and explicitly shown in the code.

I could add pages to this discussion supporting your points
further. Been there, paid my dues.

>The secondary issue, that is particularly relevant in embedded systems
>where code size and speed is often important, is that exceptions can
>cripple your optimiser, and generate larger and slower code. At
>multiple points in the generated code, the compiler has to add code to
>deal with exceptions - for every function call that might throw an
>exception (including every function whose definition is not known and is
>not declared with noexcept), the compiler has to assume that an
>exception will be thrown. That means stack unwinding, destructors being
>called, etc. This can mean lots of overhead in code space and stack
>space, the compiler's optimiser is hindered in re-ordering code, common
>subexpression optimisations, etc.

Again, you can go back to comp.arch.embedded and find posts
from me going on for pages and pages making these points and
much more and explaining why I can't use C++ for most
embedded work -- for these reasons and a few more.

However, that doesn't mean I wouldn't benefit from C++
semantics in embedded applications. Namespaces cost ZERO code
and provide a benefit I'd use, just to name a simple one.
Another would be references. There are many, many others
where the cost is quite predictable and very low and the
semantic power would improve the quality of the source code.
The use of lambdas being one I have harped on, after my own
fashion, for many years (here included.) I just used lambdas
for a commercial product and it GREATLY improved the result,
made it more readable and maintable and explainable -- even
to those who had never been exposed to them before.

Exceptions and (before partial template specialization)
templates were two areas I stayed completely clear of in
embedded use, to name two areas. (There are more.)

But I like to pick and choose and I consider more options to
be better than fewer. I don't have to use them. But if they
help me, I will. I'm not a black and white, it's A or B, kind
of person.

Jon
> Code that looks like:
>
> .
> .
> .
> x();
> string y;
> x();
> .
> .
> .
>
> Assume this resides in a module (file) where it looks exactly
> like C (no exceptions, no try blocks, no use of exceptions,
> etc.) and the only thing in all the code is that in ONE place
> it specifies the construction of an object (y) that must be
> destroyed if x(), which we will assume for now resides in a
> different module where the source code is NOT visible to the
> compiler, generates a throw. The first call to x() doesn't
> need to trap anything, as there is nothing prior needing
> destruction. The second call to x() does need such a hidden
> mechanism because C++ is forced to deal with destroying y if
> such an exception were to take place. And it doesn't know,
> since it can't see the code for x(). I was hoping noexcept
> would permit me to inform the compiler that it doesn't need
> to worry so it can produce the same code for both calls to
> x() (or, another way of saying it, it doesn't need to insert
> exception handling to destroy y in the case of a throw but
> only needs to destroy y in a non-exception context of the
> current code.)

If you are concerned about C++'s default exception handing in this situation, you would not write it this way. You would make the constructors for string() private and expose a no-throw operator new and use dynamic allocation and null tests, just like in regular C. Sure, you pay for allocation but dot with placement-new with no throw. It's a bit nasty as an API, but there you go...

I would also say that these days, with the latest in link time optimisation (a technique that is indeed very old, but only now being put to good use with excessive compute power and cheap RAM), nothing is invisible to the linker and it will code generate. This is rather like the old MIPS ucode approach. GCC has it with link-time optimisation (LTO) and clang+LLVM have it with their bitcode files too. So, such transformations are now accessible, but whether they are performed is another matter.

>
> In any case, more control is better in my mind. Gives me more
> options, not fewer. The way you talk, you don't want options
> but want only BLACK and WHITE thinking processes.
>
> I'm not like that.
>
>> The main problem with exceptions is the obvious one - it makes it very
>> difficult to guess the control flow of the program. You can get
>> unexpected jumps at odd times, and you have to be /extremely/ rigorous
>> and structured in your programming to be sure you have full control.
>> With half that discipline you can get the same benefits from passing
>> error conditions and checking return values in the traditional C manner,
>> and having it clearly and explicitly shown in the code.
>
> I could add pages to this discussion supporting your points
> further. Been there, paid my dues.

Exceptional programming, with Ada's exceptions, looked so good to a novice programmer. How bad it turned out to be. Your nice, readable code turned into a mess of exception handlers for things that would very rarely go wrong but would take an inordinate amount of time to code for.

>
>> The secondary issue, that is particularly relevant in embedded systems
>> where code size and speed is often important, is that exceptions can
>> cripple your optimiser, and generate larger and slower code. At
>> multiple points in the generated code, the compiler has to add code to
>> deal with exceptions - for every function call that might throw an
>> exception (including every function whose definition is not known and is
>> not declared with noexcept), the compiler has to assume that an
>> exception will be thrown. That means stack unwinding, destructors being
>> called, etc. This can mean lots of overhead in code space and stack
>> space, the compiler's optimiser is hindered in re-ordering code, common
>> subexpression optimisations, etc.
>
> Again, you can go back to comp.arch.embedded and find posts
> from me going on for pages and pages making these points and
> much more and explaining why I can't use C++ for most
> embedded work -- for these reasons and a few more.
>
> However, that doesn't mean I wouldn't benefit from C++
> semantics in embedded applications. Namespaces cost ZERO code
> and provide a benefit I'd use, just to name a simple one.

Namespaces are part of the EC++ "standard" (subset). C's maxim has always been that you don't pay for what you don't use. In this case, namespaces have no runtime penalty, so they were admitted to EC++.

> Another would be references. There are many, many others
> where the cost is quite predictable and very low and the
> semantic power would improve the quality of the source code.

Have to say, I really don't like references in C or C++ code (or even XC code for that matter) but they are matter-of-fact in Pascal-class languages (derived from Algol's ref type).

-- Paul.

On 17/06/12 02:00, Jon Kirwan wrote:
> On Sat, 16 Jun 2012 23:11:29 +0200, you wrote:
>
> >I am not sure if noexcept will negate all the bad points about
> >exceptions
>
> I never speak in absolutes -- except when saying that I
> absolutely don't do so. :)
>

And I /always/ speak in absolutes - well, most of the time :-)

> I hope I didn't imply that noexcept would negate _all_ bad
> points.

No, you didn't imply that.

> I just thought it was a potentially useful addition
> for some circumstances. It seems attractive, in that I
> believe it may inform the compiler that it does NOT need to
> generate exception handlers in code that doesn't specify any,
> just to handle destruction of an object that _might_ need
> destruction if some call to a function might cause an
> exception.
>
> Code that looks like:
>
> .
> .
> .
> x();
> string y;
> x();
> .
> .
> .
>
> Assume this resides in a module (file) where it looks exactly
> like C (no exceptions, no try blocks, no use of exceptions,
> etc.) and the only thing in all the code is that in ONE place
> it specifies the construction of an object (y) that must be
> destroyed if x(), which we will assume for now resides in a
> different module where the source code is NOT visible to the
> compiler, generates a throw. The first call to x() doesn't
> need to trap anything, as there is nothing prior needing
> destruction. The second call to x() does need such a hidden
> mechanism because C++ is forced to deal with destroying y if
> such an exception were to take place. And it doesn't know,
> since it can't see the code for x(). I was hoping noexcept
> would permit me to inform the compiler that it doesn't need
> to worry so it can produce the same code for both calls to
> x() (or, another way of saying it, it doesn't need to insert
> exception handling to destroy y in the case of a throw but
> only needs to destroy y in a non-exception context of the
> current code.)
>
> That's not much of an improvement. But it is an improvement
> that might open an option, which would otherwise be closed to
> me.
>

Yes, I think that's the aim of noexcept. Basically, the idea is to have
something that does what people think "throw()" does (i.e., it says that
the function will never throw an exception). Many C++ compilers already
have extensions for this (such as gcc's "nothrow" attribute).

> >- you'd have to be consistent about using it everywhere, in
> >which case it is easier just to disable exceptions entirely (I would be
> >surprised if there were any embedded C++ compilers that don't have a
> >flag for disabling exceptions).
>
> Here, I simply think you continue to speak in extremes. I am
> speaking entirely in moderation. It is not the case that
> either I want exceptions everywhere or else I want them
> nowhere. That is extreme-minded mentality operating. Not
> nuanced thinking.

That's entirely true.

Sometimes a happy medium is the best solution - one where you can use
exceptions when you need them, and use "noexcept" to avoid the overhead
when you don't need them.

But I stand by my point that if you are going to allow exceptions at all
and in any way, then you have to be very careful about being consistent
and accurate all the way. Any time you omit a "noexcept" on a function,
you risk code bloat (such as you described in your example above). And
for a function to be "noexcept", then you have to be sure that all the
functions /it/ calls are also "noexcept", unless you include the
overhead of catching and handling potential exceptions. And if you mark
a function as "noexcept" and it actually /can/ throw an exception, you
get a complete mess. The compiler can probably check most of these
circumstances (assuming you are also careful about your declarations and
definitions, so that you never end up declaring a function "noexcept" in
one header but defining it without "noexcept" in another file), but it
can't check everything.

Will "noexcept" be useful? I think probably it will, for programs that
use exceptions. Will it significantly help? I suspect not, unless you
you work hard to do so (but unlike "throw()", it is unlikely to make
things worse). Will I use it in embedded C++ code? Not a chance - I'll
disable exceptions entirely. But that absolute rule is for /me/ -
others can take it or leave it.

(Note that I do use exceptions in other circumstances - I have found
them useful in Python programming. But embedded programming an Python
programming on a PC are not the same thing.)

>
> There are cases where it would be important to me in some
> places in an application that I am absolutely certain that
> the burden of exception handling isn't being generated but
> where elsewhere in the application such handling would be
> fine.
>

If you need that, then "noexcept" is a good idea.

> In any case, more control is better in my mind. Gives me more
> options, not fewer. The way you talk, you don't want options
> but want only BLACK and WHITE thinking processes.
>

I don't have anything against giving /you/ an option here - I /choose/
not to give /myself/ the option. I will also recommend this opinion to
others, but it is always up to others whether they follow it or not.

Rules and recommendations are different for different people, different
tools, different program types, etc.

> I'm not like that.

I know :-)

However, I am also not as absolutist as you think, or as I often appear.
There are times when rules get bent or broken. Think of my opinions
more like the "shall" rules of Misra, rather than mathematical laws. If
you really want to break them, you can beg permission and forgiveness
from the project manager, and carefully document /why/ you want to break
them - then its fair enough.

I like to keep things simple where possible. Shades of grey are often
unavoidable, but if you can stick to black and white, it's much easier
to write code that is clear, readable, correct, and easily seen to be
correct. Isn't that a good aim?

>
> >The main problem with exceptions is the obvious one - it makes it very
> >difficult to guess the control flow of the program. You can get
> >unexpected jumps at odd times, and you have to be /extremely/ rigorous
> >and structured in your programming to be sure you have full control.
> >With half that discipline you can get the same benefits from passing
> >error conditions and checking return values in the traditional C manner,
> >and having it clearly and explicitly shown in the code.
>
> I could add pages to this discussion supporting your points
> further. Been there, paid my dues.
>
> >The secondary issue, that is particularly relevant in embedded systems
> >where code size and speed is often important, is that exceptions can
> >cripple your optimiser, and generate larger and slower code. At
> >multiple points in the generated code, the compiler has to add code to
> >deal with exceptions - for every function call that might throw an
> >exception (including every function whose definition is not known and is
> >not declared with noexcept), the compiler has to assume that an
> >exception will be thrown. That means stack unwinding, destructors being
> >called, etc. This can mean lots of overhead in code space and stack
> >space, the compiler's optimiser is hindered in re-ordering code, common
> >subexpression optimisations, etc.
>
> Again, you can go back to comp.arch.embedded and find posts
> from me going on for pages and pages making these points and
> much more and explaining why I can't use C++ for most
> embedded work -- for these reasons and a few more.
>

C++ is an enormous language - it provides scope for a lot of good
features that would benefit many programs. But it also provides scope
for writing totally incomprehensible and uncontrolled programs. You
can, of course, write crap in any language - but C++ provides so many
more different ways of writing nonsense than most languages!

This was sort of the idea behind the EC++ subset of C++ - but
unfortunately it was not a very good subset. Removing multiple
inheritance and virtual base classes was a good thing. Removing
exceptions is also good, IMHO, although some people might disagree :-)
But removing namespaces and templates is just silly.

> However, that doesn't mean I wouldn't benefit from C++
> semantics in embedded applications. Namespaces cost ZERO code
> and provide a benefit I'd use, just to name a simple one.

Agreed /almost/ 100%. Used badly, namespaces can make it confusing to
find the right symbols compared to the simpler single global namespace
of C. But used with at least half a brain, then they are all good.

> Another would be references.

Agreed more than 100%.

> There are many, many others
> where the cost is quite predictable and very low and the
> semantic power would improve the quality of the source code.

There are several features that can greatly improve the quality of the
source, if used well, but there is a risk of getting overly complicated
and tying yourself in knots.

Classes /can/ be a very good way of encapsulating code, data, and
concepts, as long as you don't go overboard. They also have the
potential for being very inefficient if you have a processor with very
poor pointer support.

Default arguments and overloaded functions /can/ be good, but they can
also make code very confusing. Even more so for overloaded operators.

Templates can provide the power to generate very efficient code, or very
inefficient code - they need to be used with care, and with lots of
testing and reading generated assembly code.

> The use of lambdas being one I have harped on, after my own
> fashion, for many years (here included.) I just used lambdas
> for a commercial product and it GREATLY improved the result,
> made it more readable and maintable and explainable -- even
> to those who had never been exposed to them before.
>

I haven't seen the need for lambdas in embedded coding, but I have used
them regularly in Python programming. I have no specific objections to
them in C++, except that they can be hard to follow for people who are
not used to them.

> Exceptions and (before partial template specialization)
> templates were two areas I stayed completely clear of in
> embedded use, to name two areas. (There are more.)
>
> But I like to pick and choose and I consider more options to
> be better than fewer. I don't have to use them. But if they
> help me, I will. I'm not a black and white, it's A or B, kind
> of person.
>
> Jon
>
On 17/06/12 09:40, Paul Curtis wrote:
> > However, that doesn't mean I wouldn't benefit from C++
> > semantics in embedded applications. Namespaces cost ZERO code
> > and provide a benefit I'd use, just to name a simple one.
>
> Namespaces are part of the EC++ "standard" (subset). C's maxim has
> always been that you don't pay for what you don't use. In this case,
> namespaces have no runtime penalty, so they were admitted to EC++.
>

It's perhaps a minor point, but namespaces are /not/ part of the EC++
subset.



If there is ever an update to EC++, then namespaces will probably be
added, since they have no overheads.
On Sun, 17 Jun 2012 08:40:47 +0100, you wrote:

> If you are concerned about C++'s default exception handing
> in this situation, you would not write it this way. You
> would make the constructors for string() private and expose
> a no-throw operator new and use dynamic allocation and null
> tests, just like in regular C. Sure, you pay for allocation
> but dot with placement-new with no throw. It's a bit nasty
> as an API, but there you go...

I was trying to give a simple example to make a point. That
was as simple as I could make it. And I'm not excited by your
alternative here, either.

I'd like something that simply says "don't worry, it's not
going to happen. I know, because I'm programming this."

> I would also say that these days, with the latest in link
> time optimisation (a technique that is indeed very old, but
> only now being put to good use with excessive compute power
> and cheap RAM), nothing is invisible to the linker and it
> will code generate. This is rather like the old MIPS ucode
> approach.

I remember.

> GCC has it with link-time optimisation (LTO) and
> clang+LLVM have it with their bitcode files too. So, such
> transformations are now accessible, but whether they are
> performed is another matter.

Hmm.

Jon
On Sun, 17 Jun 2012 08:40:47 +0100, you wrote:

> Exceptional programming, with Ada's exceptions, looked so
> good to a novice programmer. How bad it turned out to be.
> Your nice, readable code turned into a mess of exception
> handlers for things that would very rarely go wrong but
> would take an inordinate amount of time to code for.

I'm not sure why you bring in a system that makes things a
"mess" applies to my responses, which were merely that I like
options I can use or not use. Perhaps this is just an
interesting side bar?

Jon
On Sun, 17 Jun 2012 08:40:47 +0100, you wrote:

> Have to say, I really don't like references in C or C++ code
> (or even XC code for that matter) but they are
> matter-of-fact in Pascal-class languages (derived from
> Algol's ref type).

I would use references because they permit a compiler to do
better optimizations. They simply do. Of course, that doesn't
mean the compiler author will do anything useful with that
fact. But they could.

Others might use them because they allow a quick-hack way of
suddenly turning a "by value" parameter into something they
can reach through and modify, breaking to earlier contract.
Maybe that is your problem. But it's not mine. I care about
better optimizations. A hope that has been repeatedly dashed
over and over again, by what I see as regression rather than
progress in that area. Supported by a few recent comments
lately here in this group by you, if I recall.

Jon
On 17/06/12 21:05, Jon Kirwan wrote:
> On Sun, 17 Jun 2012 08:40:47 +0100, you wrote:
>
> > Have to say, I really don't like references in C or C++ code
> > (or even XC code for that matter) but they are
> > matter-of-fact in Pascal-class languages (derived from
> > Algol's ref type).
>
> I would use references because they permit a compiler to do
> better optimizations. They simply do. Of course, that doesn't
> mean the compiler author will do anything useful with that
> fact. But they could.
>
> Others might use them because they allow a quick-hack way of
> suddenly turning a "by value" parameter into something they
> can reach through and modify, breaking to earlier contract.
> Maybe that is your problem. But it's not mine. I care about
> better optimizations. A hope that has been repeatedly dashed
> over and over again, by what I see as regression rather than
> progress in that area. Supported by a few recent comments
> lately here in this group by you, if I recall.
>
> Jon
>

I don't think references give the compiler much more opportunity for
optimisations than pointers do. There are a few cases - it can be
better for alias analysis, the compiler can assume they are non-zero,
they can't change, etc. But for the most part, references are syntactic
sugar for pointers.

However, I think they are often nicer than pointers because it allows
the benefits of pointers (such as avoiding copying large items by value)
without many of the risks (the compiler can check that the reference is
valid and non-zero at compile time), and with a cleaner and neater
syntax. Cleaner source code and better static error checking is the
winning point for me - better optimisations is a nice bonus.

mvh.,

David

On Sun, 17 Jun 2012 18:10:26 +0200, David wrote:

>On 17/06/12 02:00, Jon Kirwan wrote:
>> On Sat, 16 Jun 2012 23:11:29 +0200, you wrote:
>>
>> >I am not sure if noexcept will negate all the bad points about
>> >exceptions
>>
>> I never speak in absolutes -- except when saying that I
>> absolutely don't do so. :)
>>And I /always/ speak in absolutes - well, most of the time :-)

Hehe. I rule programming self with an iron fist. By this, I
mean that every single line I write (and it may surprise you
but by now I have a second "brain" that is always operating
and that forces me to do this quite literally with every line
I write, now) I am always thinking to myself, "Could I defend
this line here, by itself and in its context, to an angry
room full of expert programmers all of whom want to take me
from my job and still succeed in convincing them that it is
no worse than other alternatives and possibly better?" If I
can defend it, I will write it. If I feel it exposes me to
abuse, I find another way. That room is always present in my
mind. Always. I can't get rid of it.

So I have that. But I don't have "bright lines." Bright lines
are ignorant. They can't be debated. They cannot be
convinced. Novel situations cannot be explained to them. I
cannot defend myself to them, make arguments to them, etc.
They are simply ignorant walls, barriers. Some people need
them because that is the crutch their minds require. Mine
requires that "angry room of programmers." That is my crutch,
so to speak. Others want the bright lines, because they need
them. I prefer to actually _THINK_ all the time. Not follow
rules all the time.

That's how I see it, anyway. Rules set a floor beneath which
idiots cannot sink. The angry room sets a pinnacle that
encourages you to reach for the best within yourself.

I'm a "give me options" type who will then do his level best
to use those options only when they can be well defended.
Treat me like the professional I am. Don't treat my like a
child who needs restrictions.

>> I hope I didn't imply that noexcept would negate _all_ bad
>> points.
>
>No, you didn't imply that.

Thanks.

>> I just thought it was a potentially useful addition
>> for some circumstances. It seems attractive, in that I
>> believe it may inform the compiler that it does NOT need to
>> generate exception handlers in code that doesn't specify any,
>> just to handle destruction of an object that _might_ need
>> destruction if some call to a function might cause an
>> exception.
>>
>> Code that looks like:
>>
>> .
>> .
>> .
>> x();
>> string y;
>> x();
>> .
>> .
>> .
>>
>> Assume this resides in a module (file) where it looks exactly
>> like C (no exceptions, no try blocks, no use of exceptions,
>> etc.) and the only thing in all the code is that in ONE place
>> it specifies the construction of an object (y) that must be
>> destroyed if x(), which we will assume for now resides in a
>> different module where the source code is NOT visible to the
>> compiler, generates a throw. The first call to x() doesn't
>> need to trap anything, as there is nothing prior needing
>> destruction. The second call to x() does need such a hidden
>> mechanism because C++ is forced to deal with destroying y if
>> such an exception were to take place. And it doesn't know,
>> since it can't see the code for x(). I was hoping noexcept
>> would permit me to inform the compiler that it doesn't need
>> to worry so it can produce the same code for both calls to
>> x() (or, another way of saying it, it doesn't need to insert
>> exception handling to destroy y in the case of a throw but
>> only needs to destroy y in a non-exception context of the
>> current code.)
>>
>> That's not much of an improvement. But it is an improvement
>> that might open an option, which would otherwise be closed to
>> me.
>
>Yes, I think that's the aim of noexcept. Basically, the idea is to have
>something that does what people think "throw()" does (i.e., it says that
>the function will never throw an exception). Many C++ compilers already
>have extensions for this (such as gcc's "nothrow" attribute).

I was just glad to see some handwaving in this direction in
C++11 (or C++0x as Stroustrup has explicitly said it will
always be in his mind.)

>> >- you'd have to be consistent about using it everywhere, in
>> >which case it is easier just to disable exceptions entirely (I would be
>> >surprised if there were any embedded C++ compilers that don't have a
>> >flag for disabling exceptions).
>>
>> Here, I simply think you continue to speak in extremes. I am
>> speaking entirely in moderation. It is not the case that
>> either I want exceptions everywhere or else I want them
>> nowhere. That is extreme-minded mentality operating. Not
>> nuanced thinking.
>
>That's entirely true.
>
>Sometimes a happy medium is the best solution - one where you can use
>exceptions when you need them, and use "noexcept" to avoid the overhead
>when you don't need them.

Yes.

>But I stand by my point that if you are going to allow exceptions at all
>and in any way, then you have to be very careful about being consistent
>and accurate all the way.

David, that's MY JOB, damn it!! That's what they pay me to
do! Of course I will be careful.

I hate being treated as a child, David. I've been programming
actively since 1973, for gosh sake.

And I agree with you about consistency. If there is ANYTHING
that counts in helping other professionals (not children, but
professionals) to read your code it will NOT be the rules you
apply but the consistency with which you apply your own
rules. Any professional with any experience will soon figure
out what you are doing and "lock in" on it. Then the rest
becomes much easier going. It's just a "calibration period"
as they get a bead on it. But so long as you are consistent,
a professional can rapidly get on track with it and proceed.

>
>Will "noexcept" be useful? I think probably it will, for programs that
>use exceptions. Will it significantly help? I suspect not, unless you
>you work hard to do so (but unlike "throw()", it is unlikely to make
>things worse). Will I use it in embedded C++ code? Not a chance - I'll
>disable exceptions entirely. But that absolute rule is for /me/ -
>others can take it or leave it.

I've used C++ for embedded applications with exceptions
turned off, among other things I also disabled or avoided.
But like I said, if I could imagine successfully arguing a
case in front of that room of programmers, then I would use
it. I mainly focus on if the design I am considering is the
better design for the client. If it is, and if that better
design involves some use of noexcept and some places where
exceptions are permitted, then I want the chance to make that
argument in my mind and then with the client.

I don't know when that will happen, or if it will happen in
the rest of my life again. But I'd rather have the option to
consider, than not to have it. Even if I decide against it.

>(Note that I do use exceptions in other circumstances - I have found
>them useful in Python programming. But embedded programming an Python
>programming on a PC are not the same thing.)

:)

>> There are cases where it would be important to me in some
>> places in an application that I am absolutely certain that
>> the burden of exception handling isn't being generated but
>> where elsewhere in the application such handling would be
>> fine.
>
>If you need that, then "noexcept" is a good idea.

Yes.

A focus is writing maintainable and explainable code that
others will find easier to follow, modify for likely areas of
modification, and support in the longer term. This includes a
lot of factors to consider, of course. It's not likely that
I'd choose a course that includes exceptions on smaller
embedded applications. But one area where I like them because
they are cleaner than setjmp and longjmp is in some cases
where a customer wants a separate thread setup to handle
serial port command/query parsing. The code is much cleaner
and more easily read and maintained (in some cases here)
where the parser doesn't use status values everywhere (which
makes it very ugly) and instead uses exceptions to handle the
unusual cases of lexing and parsing errors. I would have to
show code to make the point clearer, but I suspect you've
done enough of it to mentally manufacture some examples on
your own. (If you can't come up with any, you haven't had
enough experience or else you know something I have never
been exposed to yet.)

>> In any case, more control is better in my mind. Gives me more
>> options, not fewer. The way you talk, you don't want options
>> but want only BLACK and WHITE thinking processes.
>
>I don't have anything against giving /you/ an option here - I /choose/
>not to give /myself/ the option. I will also recommend this opinion to
>others, but it is always up to others whether they follow it or not.

Each of us must do what works better for us.

>Rules and recommendations are different for different people, different
>tools, different program types, etc.

I suppose so.

>> I'm not like that.
>
>I know :-)
>
>However, I am also not as absolutist as you think, or as I often appear.
> There are times when rules get bent or broken. Think of my opinions
>more like the "shall" rules of Misra, rather than mathematical laws. If
>you really want to break them, you can beg permission and forgiveness
>from the project manager, and carefully document /why/ you want to break
>them - then its fair enough.
>
>I like to keep things simple where possible. Shades of grey are often
>unavoidable, but if you can stick to black and white, it's much easier
>to write code that is clear, readable, correct, and easily seen to be
>correct. Isn't that a good aim?

It's a good aim. I just don't agree that sticking to black
and white is the always-better way to achieve it. Sometimes
it is, sometimes not.

This recent example I just went through using lambdas is a
case in point where I actually made a choice to use something
NONE of my client's programmers had EVER experienced before
in their lives. That was a difficult choice for me and I
worried a lot about it. But after trying it without their
use, I knew it was wrong. So I made the decision to use the
lambdas and it not only greatly improved the quality of the
code, it also moved the code much closer to their own stated
goals, and when I set out to do a code walkthrough the
response I got wasn't concern or worry but was instead

"we need to start doing this ourselves, this is so easy
to understand and maintain, and it makes so much sense."

I had expected worse. They are sticklers for rules and I knew
that. These are long-term programmers who have stayed with
the same corporation, most of them, for more than 20 years
now. They know their product and have a very large amount of
software they support (and sell.) I was actually worried, but
I also KNEW that this was the RIGHT APPROACH in this
particular case.

And it appears I was able to convince them, too.

I want the options to make such choices. I won't always use
those options. But I want the options so that I may make that
choice if I feel it is the right time and place for them.

>> >The main problem with exceptions is the obvious one - it makes it very
>> >difficult to guess the control flow of the program. You can get
>> >unexpected jumps at odd times, and you have to be /extremely/ rigorous
>> >and structured in your programming to be sure you have full control.
>> >With half that discipline you can get the same benefits from passing
>> >error conditions and checking return values in the traditional C manner,
>> >and having it clearly and explicitly shown in the code.
>>
>> I could add pages to this discussion supporting your points
>> further. Been there, paid my dues.
>>
>> >The secondary issue, that is particularly relevant in embedded systems
>> >where code size and speed is often important, is that exceptions can
>> >cripple your optimiser, and generate larger and slower code. At
>> >multiple points in the generated code, the compiler has to add code to
>> >deal with exceptions - for every function call that might throw an
>> >exception (including every function whose definition is not known and is
>> >not declared with noexcept), the compiler has to assume that an
>> >exception will be thrown. That means stack unwinding, destructors being
>> >called, etc. This can mean lots of overhead in code space and stack
>> >space, the compiler's optimiser is hindered in re-ordering code, common
>> >subexpression optimisations, etc.
>>
>> Again, you can go back to comp.arch.embedded and find posts
>> from me going on for pages and pages making these points and
>> much more and explaining why I can't use C++ for most
>> embedded work -- for these reasons and a few more.
>
>C++ is an enormous language - it provides scope for a lot of good
>features that would benefit many programs. But it also provides scope
>for writing totally incomprehensible and uncontrolled programs. You
>can, of course, write crap in any language - but C++ provides so many
>more different ways of writing nonsense than most languages!

:)

>This was sort of the idea behind the EC++ subset of C++ - but
>unfortunately it was not a very good subset. Removing multiple
>inheritance and virtual base classes was a good thing. Removing
>exceptions is also good, IMHO, although some people might disagree :-)
>But removing namespaces and templates is just silly.

I can only guess about templates, but it may have been that
they couldn't insist on partial template specialization. I
would make that part of the spec, a rock hard requirement, if
I permitted templates in embedded.

>> However, that doesn't mean I wouldn't benefit from C++
>> semantics in embedded applications. Namespaces cost ZERO code
>> and provide a benefit I'd use, just to name a simple one.
>
>Agreed /almost/ 100%. Used badly, namespaces can make it confusing to
>find the right symbols compared to the simpler single global namespace
>of C. But used with at least half a brain, then they are all good.

You know? I like to imagine I have half a brain. Allow me
that much hope?

>> Another would be references.
>
>Agreed more than 100%.

My reason is because it permits optimizations you can't be
sure of, otherwise. (Stroustrup discusses this as his early
motivation in some old text I'd read from him many years
ago.)

>> There are many, many others
>> where the cost is quite predictable and very low and the
>> semantic power would improve the quality of the source code.
>
>There are several features that can greatly improve the quality of the
>source, if used well, but there is a risk of getting overly complicated
>and tying yourself in knots.

You always sound like you are so worried about neophytes
whose hands you must hold and coddle and for whom you must
set up restrictions and rules so they don't do something
dumb. You worry about the floor of performance.

I worry about doing the best I can for my clients. If I was
always worried I would fall through the floor, I'd stop
programming entirely because my clients don't deserve to be
helped by someone who needs a performance floor to keep them
from falling through.

>Classes /can/ be a very good way of encapsulating code, data, and
>concepts, as long as you don't go overboard. They also have the
>potential for being very inefficient if you have a processor with very
>poor pointer support.

I spent a lot of time studying exactly HOW classes are
implemented. This includes how inheritance, multiple and
otherwise, are managed. It's very interesting. But I did that
because I need to know WHAT I would be doing if I used them.

Again, my point here is that I'm not ignorant.

>Default arguments and overloaded functions /can/ be good, but they can
>also make code very confusing. Even more so for overloaded operators.

Not enough space here, or time, to go into this. But yes and
no and maybe all apply here. Again, these are options to
consider, not necessarily use. If I can argue that an
overloaded function is best for the client, then I'd use it.
Same would be true of operators, but I also have to be aware
of conversion operators that may also be present and permit
unintended connections.

A comprehensive view would take all this into account. If it
isn't appropriate, and it is risky to do, then don't do it.
If it is the better option in a particular case and you can
make that point stick to a room full of angry programmers,
then go for it. So far, I've not used overloaded operators in
a professional embedded product, though.

>Templates can provide the power to generate very efficient code, or very
>inefficient code - they need to be used with care, and with lots of
>testing and reading generated assembly code.

Code bloom, without specialization, can readily occur. But
again, everything is nuanced and there are no bright lines in
my mind. If I comprehensively inform myself and decide that
it is the better approach for a client, then I'd use them. I
haven't, yet, for embedded.

>> The use of lambdas being one I have harped on, after my own
>> fashion, for many years (here included.) I just used lambdas
>> for a commercial product and it GREATLY improved the result,
>> made it more readable and maintable and explainable -- even
>> to those who had never been exposed to them before.
>
>I haven't seen the need for lambdas in embedded coding, but I have used
>them regularly in Python programming. I have no specific objections to
>them in C++, except that they can be hard to follow for people who are
>not used to them.
>

Oh, cripes. I've been using iterator concepts and lazy
evaluation for decades with good results. These are subsets
of lambda calculus, as I'm learning more now. But it is a
VERY POWERFUL concept. One I've been using for almost two
decades already because they work so well and improve the
quality of the resulting code. If you are interested in
seeing a good example, I'd be happy to show you how why they
helped me recently and allow you to consider the alternative
options to see why this is the better way to handle what I
faced.

And they are NOT AT ALL hard to follow!! The C++11 syntax is
the ugliest, most vile way of specifying them I can imagine.
It's despicable. But that is syntax, not semantics.
Semantically, they are a thing of beauty and simplicity
itself. Anyone can get the idea. Anyone. I just spent a few
days doing a code review to programmers who'd never been so
much as even exposed to the concept, let alone the syntax.
And they came away wondering out loud why they'd never
bothered to learn about it before.

It took me 5 minutes to get the idea across so that they
actually understood it.

They are not "hard to follow."

Jon