[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [lmi] Using unnsigned
From: |
Vadim Zeitlin |
Subject: |
Re: [lmi] Using unnsigned |
Date: |
Mon, 28 Mar 2016 23:10:22 +0200 |
On Mon, 28 Mar 2016 20:47:26 +0000 Greg Chicares <address@hidden> wrote:
GC> On 2016-03-28 15:07, Vadim Zeitlin wrote:
GC> > On Mon, 28 Mar 2016 14:41:32 +0000 Greg Chicares <address@hidden> wrote:
GC> [...]
GC> > GC> [Using] signed integers in the interface as a general rule avoids
[...]
GC> > GC> problems and lets us write simpler code, faster.
GC> >
GC> > This would result in reducing everything to the lowest common denominator
GC> > of C-like APIs.
GC>
GC> All right, you envision a world where C-like APIs have been banished or at
least
GC> sequestered, so that we can write clear code in C++ as a high-level
language.
GC> I'm not convinced that we've yet entered that new world, but I wouldn't
object
GC> to it.
I can't seriously pretend that we left C behind because this is clearly
not the case yet and might never be completely. But I certainly want to
move in this direction and this is not new nor even related to C++11: the
natural instinct to replace C fopen/close() with a RAII wrapper which I
have since 20+ years is just another expression of the same motivation.
GC> I don't disagree that
GC> std::optional<SomeIntegerType> wxChoice::GetSelection()
GC> would be better; it's just not available yet.
Unfortunately it's true and seems unlikely to change in the near future
(I'd like to make a clean, C++-whatever, façade over wx API, but this is a
lot of work...). However nothing can prevent lmi from defining its own
get_selection(wxControlWithItems&) free function behaving like this.
GC> > GC> In the C family, it's customary to use "impossible" negative values to
GC> > GC> represent errors:
GC> >
GC> > I would say "in C" instead of "C family".
GC>
GC> There, I think, is the crux of our apparent disagreement. I do think of C++
as
GC> a better C, but don't yet think of it as transcending C. Can it do so
without
GC> losing execution speed?
I definitely believe so -- and have never seen any example disproving it.
GC> I've recently been talking with someone who wants to write a large
GC> system that must be very fast, and he's leery of C++'s possible
GC> overhead, while I question that objection.
I know of plenty C++ projects which were over time/budget, had too many
bugs and experienced various other failure modes. I've never heard about a
project using C++ which had to be rewritten in C because it was not fast
enough. The closest I can think of is writing some truly critical parts in
assembly but you just don't gain anything by replacing C++ with C.
Of course, in theory it's possible to do something completely stupid, e.g.
throw and catch an exception (or, maybe more realistically, have tons of
memory allocations) in a tight inner loop. But it would still be easily
correctable in C++ without going down to C and I think that any programmer
capable of doing something like this would find a way to do even worse
things in C too.
GC> I haven't yet studied the C++11 changes; have the designers made stuff
GC> like std::optional work at C speed?
Yes, it is supposed to be optimal, in particular it won't perform any heap
allocations for ints.
GC> On this last point we still don't agree. I'd agree if we had a
GC> 'nonnegative int' datatype,
This could be another possibility, e.g. an UI framework could have
wxControl::ItemIndex type which would be a simple wrapper around int (or
unsigned int, it doesn't matter as long as it's encapsulated). But I'm
afraid that this might be too much abstraction to be useful, people really
want to use indices as numbers.
GC> But 'unsigned int' is not such a datatype. Rather, it's a low-level C
concept.
GC> These correspondences:
GC> unsigned int <-> nonnegative integers
GC> signed int <-> integers
GC> are arguably looser than
GC> double <-> real numbers
GC> In particular, decrementing the nonnegative integer zero by one is an error,
GC> while 0U - 1 returns some Mersenne number. I don't think of C's unsigned
types
GC> as nonnegative; I think of them as the least residue system modulo
2^word-size.
GC> Obeying modular arithmetic is their salient characteristic; imagining
'unsigned'
GC> to mean 'nonnegative' leads us into the 0U-1 trap.
Again, I agree that unsigned types in C++ are not perfect. But I still
think that just the extra information carried by them is worth using them.
When you see a function declared as returning unsigned, you know you can
rely on its return value being positive and this is valuable. Maybe
unsigned doesn't really mean nonnegative for the compiler, but it
definitely does mean it for the human reader of the code and, as we know,
programs should be written with the latter and not the former in mind.
GC> When we perform arithmetic on wxChoice::GetSelection()'s result, we're
GC> very unlikely to stumble outside [INT_MIN, INT_MAX], but quite likely
GC> to stumble on 0U-1; and 0-1 (signed) has less startling behavior.
I don't really see how is using -1 as an index any better than using
UINT_MAX, so it's not like arithmetic with signed integers is devoid of
danger. As long as you check the resulting values before using them, e.g.
as is done by std::vector::at(), both errors will be detected. As long as
you don't, e.g. with std::vector::operator[](), both will be fatal.
And the point about unsigned types being better from the point of view of
interoperability with the standard library still remains too.
VZ