From: Francis Glassborow on
Balog Pal wrote:
> "Daniel T." <daniel_t(a)earthlink.net>

>
>> That said, many people have no problem with using break or continue to
>> jump out of the middle of a block of code and maybe you are one of them.
>
> Of course. :) And I could add that I'm not afraid of using goto
> either if (if!!!) that comes up as the best solution for the case --
> just it is damn rare in C++.
>
> Believe me, being dogmatic is a bad thing. To go a little back to
> originals -- If you were on my interview, a statement like you did,
> being dogmatic SESE would map to an automatic "no hire" (after
> clarifying you actually mean it). Because I stick to wizard rule #6 --
> my only sovereign is REASON. Dogmaitsm is the very opposite of
> reason. I expect programmers to always be aware what they do, and be
> able to provide a rationale -- fit for the particular case. Just as
> guidelines (any guidelines) are only as good as they are understood --
> and wielder can regress them to roots. (See also "the five whys" from
> lean.)
>
>> I consider it a style issue more than anything else. Some people have no
>> problem exiting blocks of code all over the place, I try not to.
>
> You skipped over the my mentioning exceptions. As exceptions can
> happen, it is no longer just a style, and if one thinks some layout
> *has* the actual SESE property just by restricting to a single return --
> is quite mislead. Thus imposing danger.

Yes I agree with much of this but would like to refine it a bit. For me
source code clarity is of very great importance. Much of the time the
compiler will be able to produce a good executable given clear code and
clear code is much more likely to do what it appears to do.

One thing that irritates me with the SESE camp is that many of them
actually do not understand that it is more than just avoiding multiple
exits it is about structuring your code in such a way that a single exit
is natural and not being contrived by having extra variables.

And the SEME camp contains a good number of people whose code lacks
clarity because they just bail out at any old point.

For example if I code a switch statement I am happy for every case to
end with return or for none of them to do so but generally would not
encourage a mixture because now I have much more to do in order to
understand when code after the end of the switch executes.

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

From: Mathias Gaunard on
On Mar 2, 5:23 am, "Daniel T." <danie...(a)earthlink.net> wrote:
> I had a job interview recently and I was asked to write three functions
> on a sheet of paper. I was given 45 minutes for this task.

The exercises you were given were pretty silly, and your answers show
that you know C++ well, better than they actually do.
If you're interested in C++ programming rather than C compiled as C++,
I'd suggest you try to look for another job.


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

From: Nevin :-] Liber on
In article
<daniel_t-08C109.11084504032010(a)70-3-168-216.pools.spcsdns.net>,
"Daniel T." <daniel_t(a)earthlink.net> wrote:

> In my experience (and it might be just in my domain,) if an exception is
> thrown, then it is because a programmer made an unwarranted assumption
> while writing some particular piece of code and the code should be fixed
> so the exception is no longer thrown.

(In my problem domain, you are describing ASSERT, not exceptions.)

I'm confused. In some of your examples, you use STL constructs (such as
vector and string), which can throw. For example, in article
<daniel_t-E21C8D.22124501032010(a)70-3-168-216.pools.spcsdns.net>, you
wrote:

> void permutations(const char* in)
> {
> vector<string> strs;
> stringstream ss(in);
> string next;
> while (ss >> next) {
> strs.push_back(next);
> }
> copy(strs.begin(), strs.end(), ostream_iterator<string>(cout, " "));
> cout << '\n';
> while (next_permutation(strs.begin(), strs.end())) {
> copy(strs.begin(), strs.end(),
> ostream_iterator<string>(cout, " "));
> cout << '\n';
> }
> }

How do you avoid things like vector and string from throwing exceptions?

--
Nevin ":-)" Liber <mailto:nevin(a)eviloverlord.com> 773 961-1620

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

From: Dave Harris on
magnicida(a)gmail.com (Juan Pedro Bolivar Puente) wrote (abridged):
> >> // Answer 1
> >> bool fn(char a, char b)
> >> {
> >> bool result = false;
> >> if (tolower(a) == tolower(b))
> >> result = a > b;
> >> else
> >> result = tolower(a) < tolower(b);
> >> return result;
> >> }
> >
> > I'd definitely not like that one, and prefer
> > const int lo_a = tolower(a);
> > const int lo_b = tolower(b);
> > if(lo_a == lo_b)
> > return a > b;
> > else
> > return lo_a < lo_b;
> [...]
> Anyway, the only advantage of your solution is that it might be a
> bit more efficient if the compiler is not able to discover that
> tolower() has no side-effects when inlining it...

Tolower() ought to handle locales. I wouldn't bet on the compiler fully
inlining it.

Also, the original version requires the human reader to know that
tolower(x) == tolower(y) when x == y. The second version makes explicit
that the values compared for equality are the same values compared in the
final return. It's not just a performance optimisation, it's clearer code.
Write what you mean; don't write something different and then hope the
optimiser will turn it into what you mean.


> On the other hand, his solutionhas the advantage that fits the
> "only one return point" principle that many people are dogmatic
> about --and maybe his interviewer is one of them (I know,
> your solution could be adapted to match that property).

I think the main point of his solution was to eliminate the result
variable. Some of us are dogmatic about needless mutable state.
Reassignment is the root of all evil, you know.

Personally I'd see it as an example of a lexical compare, which I usually
write:
if (lhs.part_a != rhs.part_a)
return lhs.part_a < rhs.part_a; if (lhs.part_b != rhs.part_b)
return lhs.part_b < rhs.part_b;
if (lhs.part_c != rhs.part_c)
return lhs.part_c < rhs.part_c;
// ...
return false; // lhs == rhs.

This extends naturally to arbitrarily many parts, without hugely nested
cases or indentation.


> In any case, if you really care that much about about performance,
> here is a just for fun new implementation for very picky boys ;)
>
> bool f (char a, char b)
> {
> const char d = a - b;
> if (a >= 'a') {
> if (b < 'a')
> return d <= 'a' - 'A';
> return d < 0;
> }
> if (b >= 'a')
> return d < 'A' - 'a';
> return d < 0;
> }

In addition to the assumption of Ansi etc noted elsewhere, it assumes
char is signed. It won't work with, for example, VC++ with /J on the
command line.

-- Dave Harris, Nottingham, UK.

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

From: Balog Pal on
"Daniel T." <daniel_t(a)earthlink.net>
> Gerhard Menzl <clcppm-poster(a)this.is.invalid> wrote:
>> Daniel T. wrote:
>>
>> > I am pretty dogmatic about the single exit principle. I've had too
>> > many times when I was trying to find some hard to track bug in
>> > someone else's code only to learn that it had to do with some early
>> > return or continue that bypassed a critical piece of code.
>>
>> So you're using C++ without exceptions then?
>
> I don't use exceptions for normal control flow.
>
> In my experience (and it might be just in my domain,) if an exception is
> thrown, then it is because a programmer made an unwarranted assumption
> while writing some particular piece of code and the code should be fixed
> so the exception is no longer thrown.

Ouch. Do you (or people around you) confuse exceptions with assert? Those
things are absolutely not interchangeable.

You throw exceptions for some *runtime* conditions detected that are ought
not happen, but possible (like out of resources, filesystem-problems,
communication or DB timeout, etc). There is no way to get rid of them by
whatever shape of code.

And exceptions like bad_alloc can be emitted by too many mundane constructs.
If you use vector, string and similar stuff, the code shall be
exception-aware even if you never code a line saying 'throw' ever.



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