Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

"Use Stronger Types!"

207 views
Skip to first unread message

Lynn McGuire

unread,
Nov 3, 2016, 7:34:07 PM11/3/16
to

woodb...@gmail.com

unread,
Nov 3, 2016, 11:06:45 PM11/3/16
to
Jorgen Grahn has been saying something similar here in
the past.

Mr Flibble

unread,
Nov 4, 2016, 10:30:45 AM11/4/16
to
On 03/11/2016 23:33, Lynn McGuire wrote:
> "Use Stronger Types!"
> http://arne-mertz.de/2016/11/stronger-types/

Wrapping the fundamental types with a unique domain specific wrapper
class is pure craziness; better would be a more generic constrained
template wrapper that is then typedef'd with a domain specific name:

template <typename IntegerType, IntegerType MinimumValue, IntegerType
MaximumValue>
class constrained_integer
{
public:
constrained_integer(IntegerType aValue) : iValue(aValue) { /* throw
if out of range. */ }
public:
/* accessor/mutator methods */
private:
IntegerType iValue;
};

typedef constrained_integer<unsigned int, 0u, 150u> age;

int main()
{
age oldCodger = 64u;
}

I believe there is a proper strong typedef proposal for C++ which we
might get soon that would also be useful.

/Flibble

Mr Flibble

unread,
Nov 4, 2016, 10:48:41 AM11/4/16
to
If you want to prevent two unrelated "strong types" with the same
constraints and value_type from being assigned to each other then simply
add a strong type tag:

template <typename StrongType, typename IntegerType, IntegerType
MinimumValue, IntegerType MaximumValue>
class constrained_integer
{
public:
constrained_integer(IntegerType aValue) : iValue(aValue) { /* throw
if out of range. */ }
public:
/* accessor/mutator methods */
private:
IntegerType iValue;
};

struct age_tag {};
struct order_qty_tag {};

typedef constrained_integer<age_tag, unsigned int, 0u, 150u> age;
typedef constrained_integer<order_qty_tag, unsigned int, 0u, 150u>
order_qty;

/Flibble

woodb...@gmail.com

unread,
Nov 4, 2016, 11:10:53 AM11/4/16
to
I'm somewhat persuaded by Jon Kalb's advice to not use
unsigned for quantities:

https://www.youtube.com/watch?v=wvtFGa6XJDU

.

Brian
Ebenezer Enterprises - A tale of two turkeys -- Hillary and
Trump. Please pray for the USA.

http://webEbenezer.net

Mr Flibble

unread,
Nov 4, 2016, 11:23:07 AM11/4/16
to
If this "Jon Kalb" bloke advises that then this "Job Kalb" bloke doesn't
know what he is talking about and you are wrong to follow his advice.
And no I didn't watch the video nor do I intend to.

/Flibble

jacobnavia

unread,
Nov 4, 2016, 11:53:23 AM11/4/16
to
Le 04/11/2016 à 16:22, Mr Flibble a écrit :
>> I'm somewhat persuaded by Jon Kalb's advice to not use
>> unsigned for quantities:
>
> If this "Jon Kalb" bloke advises that then this "Job Kalb" bloke doesn't
> know what he is talking about and you are wrong to follow his advice.
> And no I didn't watch the video nor do I intend to.
>
> /Flibble

int a = 1;
unsigned b = -1;

if (b < a)
printf("OK¡n");
else
printf("????¡n");

This is the problem he is talking about.

What do you say to this problem?

Of course you say there is no problem, isn't it?

Mr Flibble

unread,
Nov 4, 2016, 11:58:33 AM11/4/16
to
What I say to that problem is that you shouldn't compare signed and
unsigned values.

/Flibble

woodb...@gmail.com

unread,
Nov 4, 2016, 12:17:06 PM11/4/16
to
On Friday, November 4, 2016 at 10:53:23 AM UTC-5, jacobnavia wrote:
> Le 04/11/2016 à 16:22, Mr Flibble a écrit :
> >> I'm somewhat persuaded by Jon Kalb's advice to not use
> >> unsigned for quantities:
> >
> > If this "Jon Kalb" bloke advises that then this "Job Kalb" bloke doesn't
> > know what he is talking about and you are wrong to follow his advice.
> > And no I didn't watch the video nor do I intend to.
> >
> > /Flibble
>
> int a = 1;
> unsigned b = -1;

I don't think you reproduced that right. In the video it's

signed int a{-1};
unsigned int b{1};

Scott Lurndal

unread,
Nov 4, 2016, 12:51:40 PM11/4/16
to
jacobnavia <ja...@jacob.remcomp.fr> writes:
>Le 04/11/2016 à 16:22, Mr Flibble a écrit :
>>> I'm somewhat persuaded by Jon Kalb's advice to not use
>>> unsigned for quantities:
>>
>> If this "Jon Kalb" bloke advises that then this "Job Kalb" bloke doesn't
>> know what he is talking about and you are wrong to follow his advice.
>> And no I didn't watch the video nor do I intend to.
>>
>> /Flibble
>
>int a = 1;
>unsigned b = -1;

WTF? If you want -1, use signed.

or 'unsigned b = ~0' if you want all ones.

>
>if (b < a)

Every compiler I use will generate an error on this.
(with -Werror, which we use on all our code, otherwise
the compiler will generate a nice warning.)

Use the appropriate type for the job. If a function
returns size_t, use size_t. If it returns a size and
an error indication (-1), use ssize_t. If you need an unsigned
value, use an unsigned type. If you must mix signed and
unsigned, use signed.

Lynn McGuire

unread,
Nov 4, 2016, 2:27:13 PM11/4/16
to
I do not like unsigned. Just seems unnatural to me.

Lynn

red floyd

unread,
Nov 4, 2016, 2:42:00 PM11/4/16
to
On 11/4/2016 11:26 AM, Lynn McGuire wrote:
>
> I do not like unsigned. Just seems unnatural to me.

It makes a little more sense when defined as in Modula-2.
The type name in that language is CARDINAL.

It's natural when you think of it as counting stuff...



Daniel

unread,
Nov 4, 2016, 4:51:41 PM11/4/16
to
On Friday, November 4, 2016 at 2:27:13 PM UTC-4, Lynn McGuire wrote:
>
> I do not like unsigned. Just seems unnatural to me.
>
Kind of like the undead.

Daniel

Chris Vine

unread,
Nov 4, 2016, 5:00:07 PM11/4/16
to
On Fri, 04 Nov 2016 16:51:31 GMT
sc...@slp53.sl.home (Scott Lurndal) wrote:
> jacobnavia <ja...@jacob.remcomp.fr> writes:
> >Le 04/11/2016 à 16:22, Mr Flibble a écrit :
> >>> I'm somewhat persuaded by Jon Kalb's advice to not use
> >>> unsigned for quantities:
> >>
> >> If this "Jon Kalb" bloke advises that then this "Job Kalb" bloke
> >> doesn't know what he is talking about and you are wrong to follow
> >> his advice. And no I didn't watch the video nor do I intend to.
> >>
> >> /Flibble
> >
> >int a = 1;
> >unsigned b = -1;
>
> WTF? If you want -1, use signed.
>
> or 'unsigned b = ~0' if you want all ones.

'unsigned b = -1' is the correct form if you want all bits set on an
unsigned integer value. It is guaranteed to set all bits irrespective
of the signed representation and the size of the integer: see §4.7/2 of
C++11/14. 'unsigned b = ~0' will fail to set all bits on non-2's
complement systems (on a 1's complement system it will have the same
effect as 'unsigned b = -0' which results in no bits set after the
implicit cast to unsigned has been completed).

Lynn McGuire

unread,
Nov 4, 2016, 6:02:52 PM11/4/16
to
+1

Lynn

Öö Tiib

unread,
Nov 5, 2016, 8:12:08 AM11/5/16
to
To have type-safe quantities in crippling manner is trivial.
For quantity of "gold" in game it can be fine but in reality we need
to do some actual math not just add from "loot" and subtract in "shop".

To have quantities in useful manner is far from trivial. Perhaps best
public attempt is Boost.Units:
http://www.boost.org/doc/libs/1_61_0/doc/html/boost_units.html

Quite solid, but trying to do some math with it (for example to use it
together with some linear algebra library) may still cause lot of fun. ;)

Jorgen Grahn

unread,
Nov 5, 2016, 4:23:42 PM11/5/16
to
Yes, I have! But I think I haven't been the only one.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

Chris M. Thomasson

unread,
Nov 7, 2016, 8:15:52 PM11/7/16
to
I personally like this method. Dare I say, +1?

;^)

Tim Rentsch

unread,
Nov 12, 2016, 8:22:36 AM11/12/16
to
Lynn McGuire <lynnmc...@gmail.com> writes:

> On 11/4/2016 10:10 AM, woodb...@gmail.com wrote:
[...]
>> I'm somewhat persuaded by Jon Kalb's advice to not use
>> unsigned for quantities:
>>
>> https://www.youtube.com/watch?v=wvtFGa6XJDU
>
> I do not like unsigned. Just seems unnatural to me.

Actually just the opposite: the natural numbers are the
positive integers (and also, according to ISO[1], zero).
It is the signed integer types, which include negative
integers, that are unnatural. :)

[1] https://en.wikipedia.org/wiki/ISO_31-11#Sets

Öö Tiib

unread,
Nov 12, 2016, 2:35:37 PM11/12/16
to
Subtraction of natural number from natural number results with integer
number.

In C++ subtraction of 'unsigned' from 'unsigned' results with yet another
'unsigned' by modular arithmetic.

Therefore 'unsigned' of C++ is not natural number but unnatural number
and one has to write a wrapper around it to reach something resembling
a natural number.

Jerry Stuckle

unread,
Nov 12, 2016, 5:11:35 PM11/12/16
to
You have a full five gallon pail of water. You empty it. How many more
gallons do you have in the pail now?

--
==================
Remove the "x" from my email address
Jerry Stuckle
jstu...@attglobal.net
==================

Paavo Helde

unread,
Nov 12, 2016, 6:00:41 PM11/12/16
to
I see your smiley, but comparison with natural numbers is not actually
appropriate.

Unsigned integers might be natural, but their incarnation in C and C++
with wrapping over to some arbitrary large value is anything else than
natural. Ditto the other way: how is it natural in any way that
incrementing an unsigned integer will yield zero at some point?

For signed integers wrap-over is UB and everybody is fine with that. My
take is that wrap-over for unsigned types is not UB just in order to
support sloppy programming which produces negative numbers as
intermediate results. In other words, the wrap-over nonsense has brought
in to alleviate the inherent defect in the design of unsigned integers -
discontinuity at zero. If there were no unsigned numbers, such a hack
would not be needed.


Alf P. Steinbach

unread,
Nov 13, 2016, 6:18:36 AM11/13/16
to
Rather, the wrapping for both signed and unsigned is because it would in
general, and in particular on modern computer architectures, require
extra work to avoid it, e.g. to trap, because wrapping is the natural &
automatic result of computing with a fixed number of digits.

The choice of whether to treat it as UB (as for signed types in C++) or
to require it (as for unsigned types in C++) seems more arbitrary. The
UB does allow some optimizations of loops, because the compiler can
freely assume that there will no be wrapping (e.g., in `x < y+1`). But
since the wrapping is occasionally practically useful, it would be just
as reasonable, maybe more reasonable, to provide a way to explicitly
tell the compiler to assume no wrapping in a specified region of code.

As I recall the g++ compiler has some option to make that assumption in
general for loops, for use when one tells it to in general assume well
defined wrapping instead of UB for signed types. Which is nice. But it
only partly alleviates the problem with that compiler choosing
unpredictable rare-case speed optimization, over predictability. Since
the standard allows and to some people encourages unpredictability, I
think the choice of UB was just wrong. Today, as I see it, UB does not
give a performance edge, neither in this single case nor in general: it
just obstructs the programmer's work by adding unpredictability. :(

Cheers!,

- Alf

Gareth Owen

unread,
Nov 13, 2016, 6:29:04 AM11/13/16
to
"Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:

> The choice of whether to treat it as UB (as for signed types in C++)
> or to require it (as for unsigned types in C++) seems more
> arbitrary

On of the uses for unsigned was clearly as bit-arrays for bit-twiddling
and shifting. Having an "overflowing" left-shift be UB would make them
considerably less useful.

Defining wrapping for unsigned arithmetic them seems to follow naturally
to be consistent with that.

Öö Tiib

unread,
Nov 13, 2016, 10:32:19 AM11/13/16
to
So they made about 25% additions and 95% of multiplications of two signed
integers as undefined behavior and implementing in well-formed C or C++ what
the actual multiplication and addition instructions of all platforms do as
close to impossibly complex task. Why? Who needs that?

May be it is sabotage of large companies that propose their proprietary
languages to replace C and C++. They see it beneficial that here are
C#, Swift, Go and Java but no C nor C++.


Paavo Helde

unread,
Nov 13, 2016, 10:32:39 AM11/13/16
to
On 13.11.2016 13:28, Gareth Owen wrote:
> "Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:
>
>> The choice of whether to treat it as UB (as for signed types in C++)
>> or to require it (as for unsigned types in C++) seems more
>> arbitrary
>
> On of the uses for unsigned was clearly as bit-arrays for bit-twiddling
> and shifting. Having an "overflowing" left-shift be UB would make them
> considerably less useful.

Sure, there are data types which are useful for bit twiddling and in OS
kernel structures and of course they have strong hardware support. But
IMO these should have been called "bit registers" or something, not
"unsigned integers". An "unsigned integer" type looks for me more like
some kind of special data structure like std::complex.

Cheers
Paavo


Tim Rentsch

unread,
Nov 15, 2016, 11:56:54 AM11/15/16
to
Jerry Stuckle <jstu...@attglobal.net> writes:

> On 11/12/2016 8:22 AM, Tim Rentsch wrote:
>> Lynn McGuire <lynnmc...@gmail.com> writes:
>>
>>> On 11/4/2016 10:10 AM, woodb...@gmail.com wrote:
>>
>> [...]
>>
>>>> I'm somewhat persuaded by Jon Kalb's advice to not use
>>>> unsigned for quantities:
>>>>
>>>> https://www.youtube.com/watch?v=wvtFGa6XJDU
>>>
>>> I do not like unsigned. Just seems unnatural to me.
>>
>> Actually just the opposite: the natural numbers are the
>> positive integers (and also, according to ISO[1], zero).
>> It is the signed integer types, which include negative
>> integers, that are unnatural. :)
>>
>> [1] https://en.wikipedia.org/wiki/ISO_31-11#Sets
>
> You have a full five gallon pail of water. You empty it. How
> many more gallons do you have in the pail now?

If I had a nicely full five gallon pail I would hope that what
it's full of would be something more interesting than just water.

Tim Rentsch

unread,
Nov 15, 2016, 12:23:28 PM11/15/16
to
First off my comment was mostly just a play on words, as the
smiley face indicates.

Second, when working with whole numbers (natural numbers plus
zero), it is customary to employ 'proper subtraction', which is
defined only when the number being subtracted is no larger than
the number from which it is being subtracted (or alternatively
is defined to be zero in such cases).

Third, the comment about having to write a wrapper applies just
as much to signed integer types, if not moreso. The set of
natural numbers is infinitely large, which is not even close to
being true for either signed integer types or unsigned integer
types.

But probably most important is that operations on unsigned types
always at least produce some number, which IMO makes them more
natural than the undefined behavior that happens with signed
types.

Tim Rentsch

unread,
Nov 15, 2016, 12:52:41 PM11/15/16
to
Paavo Helde <myfir...@osa.pri.ee> writes:

> On 12.11.2016 15:22, Tim Rentsch wrote:
>> Lynn McGuire <lynnmc...@gmail.com> writes:
>>
>>> On 11/4/2016 10:10 AM, woodb...@gmail.com wrote:
>>
>> [...]
>>
>>>> I'm somewhat persuaded by Jon Kalb's advice to not use
>>>> unsigned for quantities:
>>>>
>>>> https://www.youtube.com/watch?v=wvtFGa6XJDU
>>>
>>> I do not like unsigned. Just seems unnatural to me.
>>
>> Actually just the opposite: the natural numbers are the
>> positive integers (and also, according to ISO[1], zero).
>> It is the signed integer types, which include negative
>> integers, that are unnatural. :)
>>
>> [1] https://en.wikipedia.org/wiki/ISO_31-11#Sets
>
> I see your smiley, but comparison with natural numbers is not
> actually appropriate.

Sure it is, that's what makes it funny.

> Unsigned integers might be natural, but their incarnation in C and
> C++ with wrapping over to some arbitrary large value is anything
> else than natural. Ditto the other way: how is it natural in any
> way that incrementing an unsigned integer will yield zero at some
> point?

Modular arithmetic is a well-established field of mathematics.

> For signed integers wrap-over is UB and everybody is fine with
> that. My take is that wrap-over for unsigned types is not UB just
> in order to support sloppy programming which produces negative
> numbers as intermediate results. In other words, the wrap-over
> nonsense has brought in to alleviate the inherent defect in the
> design of unsigned integers - discontinuity at zero. If there
> were no unsigned numbers, such a hack would not be needed.

My experience is the opposite of that. Those who routinely use
unsigned types for certain kinds of quantities and use cases are
IME more likely to think carefully about the programming they do
and not engage in sloppy programming. Conversely, those who
espouse a "signed types almost everywhere" approach tend not to
worry about whether overflow might occur, at least not on a
comparative basis. That seems rather an odd attitude to take,
considering the potential downsides in the two cases, but it
apparently occurs fairly often nonetheless.

Just to be clear, I don't mean to advocate that anyone change
their preferences regarding signed versus unsigned types. But I
think a blanket statement that signed types are nearly always a
better choice than unsigned types is a significant overstatement.

Alf P. Steinbach

unread,
Nov 15, 2016, 2:47:46 PM11/15/16
to
On 15.11.2016 18:52, Tim Rentsch wrote:
> I
> think a blanket statement that signed types are nearly always a
> better choice than unsigned types is a significant overstatement.

Unsigned types are good for bit-level stuff. In particular you don't
want to do left-shifts with signed integers.

Signed integers are good for numbers, numerical values, when they're not
mixed with signed integers. In particular you don't want implicit
promotion of signed quantities to unsigned ones. You don't want
expressions like `string("blah").length() < -1` in your code.

Unfortunately, while the standard library at one point seemed to be
heading in the right direction, with signed distances, the C++17 general
size function has unsigned result. It also conflates several notions of
size. This lack of standard library support -- not even in any in Boost,
as far as I know -- makes it difficult for individual programmers to
transition to non-risky types for each usage area.


Cheers!,

- Alf

Öö Tiib

unread,
Nov 15, 2016, 5:52:56 PM11/15/16
to
On Tuesday, 15 November 2016 19:23:28 UTC+2, Tim Rentsch wrote:
> Tiib <oot...@hot.ee> writes:
>
> > On Saturday, 12 November 2016 15:22:36 UTC+2, Tim Rentsch wrote:
> >> Lynn McGuire <lynnmc...@gmail.com> writes:
> >>
> >>> On 11/4/2016 10:10 AM, woodb...@gmail.com wrote:
> >>
> >> [...]
> >>
> >>>> I'm somewhat persuaded by Jon Kalb's advice to not use
> >>>> unsigned for quantities:
> >>>>
> >>>> https://www.youtube.com/watch?v=wvtFGa6XJDU
> >>>
> >>> I do not like unsigned. Just seems unnatural to me.
> >>
> >> Actually just the opposite: the natural numbers are the
> >> positive integers (and also, according to ISO[1], zero).
> >> It is the signed integer types, which include negative
> >> integers, that are unnatural. :)
> >
> > Subtraction of natural number from natural number results with
> > integer number.
> >
> > In C++ subtraction of 'unsigned' from 'unsigned' results with yet
> > another 'unsigned' by modular arithmetic.
> >
> > Therefore 'unsigned' of C++ is not natural number but unnatural
> > number and one has to write a wrapper around it to reach something
> > resembling a natural number.
>
> First off my comment was mostly just a play on words, as the
> smiley face indicates.

Ok.

>
> Second, when working with whole numbers (natural numbers plus
> zero), it is customary to employ 'proper subtraction', which is
> defined only when the number being subtracted is no larger than
> the number from which it is being subtracted (or alternatively
> is defined to be zero in such cases).

I don't think we have such universal truths. Zero is natural number
by ISO 31-11. Also there are choices to say that 42 can not be
subtracted from 24 or to say that result of subtracting 42 from 24
is -18. Those choices feel more common than to say that subtracting
42 from 24 is 0.

>
> Third, the comment about having to write a wrapper applies just
> as much to signed integer types, if not moreso. The set of
> natural numbers is infinitely large, which is not even close to
> being true for either signed integer types or unsigned integer
> types.

I suspect that we do not need larger integer numbers than for
example billion more often than we need to find out distance
between two numbers ... but don't have such statistics.

>
> But probably most important is that operations on unsigned types
> always at least produce some number, which IMO makes them more
> natural than the undefined behavior that happens with signed
> types.

That "undefined behavior" is likely a result of sabotage. Actual
hardware platforms that support signed arithmetic behave on case
of signed integer overflow in definable manner and even the
differences between behavior of different platforms could be
indicated with a value of pre-defined macro or the like.

Tim Rentsch

unread,
Nov 16, 2016, 12:11:17 PM11/16/16
to
I'm only reporting what is common in mathematical texts
that discuss what used to be called "whole numbers" (and
which the ISO document now calls "natural numbers"). I
wasn't making any claim about which usage is "right",
only explaining my own usage.

>> Third, the comment about having to write a wrapper applies just
>> as much to signed integer types, if not moreso. The set of
>> natural numbers is infinitely large, which is not even close to
>> being true for either signed integer types or unsigned integer
>> types.
>
> I suspect that we do not need larger integer numbers than for
> example billion more often than we need to find out distance
> between two numbers ... but don't have such statistics.
>
>> But probably most important is that operations on unsigned types
>> always at least produce some number, which IMO makes them more
>> natural than the undefined behavior that happens with signed
>> types.

The domain of the natural numbers is infinite. The domains
of all standard integer types are bounded, not infinite.

Also, the domain of natural numbers does not include any
negative numbers. It seems odd to say that a signed
integer type, which does include negative numbers, is
more like the natural numbers than an unsigned integer
type, which does not include negative numbers.

> That "undefined behavior" is likely a result of sabotage.

I'm at a loss to understand what you mean here. The people
who wrote the original ANSI/ISO C standard surely were not
intending to cripple the behavior of arithmetic operations
for signed integer types. Presumably the behavior was left
undefined as a reflection of a wide variety of different
possible hardware platforms, both existing at the time and
plausibly existing in the foreseeable future.

> Actual
> hardware platforms that support signed arithmetic behave on case
> of signed integer overflow in definable manner and even the
> differences between behavior of different platforms could be
> indicated with a value of pre-defined macro or the like.

Sure, such a thing could be done, but that's not part of the
language. And as far as that goes, if what is wanted is
reliable operations for signed quantities, the easiest way
to do that is very likely to represent the signed quantities
with unsigned integer types.

Tim Rentsch

unread,
Nov 16, 2016, 12:32:49 PM11/16/16
to
"Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:

> On 15.11.2016 18:52, Tim Rentsch wrote:
>> I
>> think a blanket statement that signed types are nearly always a
>> better choice than unsigned types is a significant overstatement.
>
> Unsigned types are good for bit-level stuff. In particular you don't
> want to do left-shifts with signed integers.

I agree with that.

> Signed integers are good for numbers, numerical values, when they're
> not mixed with signed integers.

I assume you meant unsigned at the end there. I agree here
also, depending on what kinds of numbers/numerical values
are involved.

> In particular you don't want implicit
> promotion of signed quantities to unsigned ones.

In some cases it works fine, in others not so much. I agree
that care and caution are called for.

> You don't want
> expressions like `string("blah").length() < -1` in your code.

Comparisons between signed types and unsigned types are
rightly viewed with suspicion, and often wrong. I can't
think of a case where the expression shown above is something
any sensible person would write.

> Unfortunately, while the standard library at one point seemed to be
> heading in the right direction, with signed distances, the C++17
> general size function has unsigned result. It also conflates several
> notions of size. This lack of standard library support -- not even in
> any in Boost, as far as I know -- makes it difficult for individual
> programmers to transition to non-risky types for each usage area.

That does sound rather troublesome. I'm not sure though that
just making everything signed is the best approach either.

Gareth Owen

unread,
Nov 17, 2016, 1:28:31 AM11/17/16
to
Tim Rentsch <t...@alumni.caltech.edu> writes:


>> You don't want
>> expressions like `string("blah").length() < -1` in your code.
>
> Comparisons between signed types and unsigned types are
> rightly viewed with suspicion, and often wrong. I can't
> think of a case where the expression shown above is something
> any sensible person would write.

No, but

if(str1.length()-str2.length() < 12) { ... }

has equally bizarre behaviour.

Richard

unread,
Nov 17, 2016, 12:59:47 PM11/17/16
to
[Please do not mail me a copy of your followup]

"Alf P. Steinbach" <alf.p.stein...@gmail.com> spake the secret code
<o0fono$fiv$1...@dont-email.me> thusly:

>Unfortunately, while the standard library at one point seemed to be
>heading in the right direction, with signed distances, the C++17 general
>size function has unsigned result. It also conflates several notions of
>size. This lack of standard library support -- not even in any in Boost,
>as far as I know -- makes it difficult for individual programmers to
>transition to non-risky types for each usage area.

Isn't the solution what the subject line is all about?

Use stronger types (practice No Naked Primitives constraint
programming to get a feel for it) to directly encapsulate the
specific meaning of values in your problem domain.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Terminals Wiki <http://terminals-wiki.org>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>

Tim Rentsch

unread,
Nov 22, 2016, 10:31:02 AM11/22/16
to
It does, for slightly different reasons. But it's easy to remedy
that problem:

if(str1.length() < str2.length()+12) { ... }

We can do a similar transformation on the original example:

string("blah").length()+1 < 0

which will likely result in a compiler warning because the (new)
condition is always false. As a general rule expressions with
unsigned types should be written to use + rather than -.

Returning to the original example, as things turned out just in
the last day or two I had occasion to write a comparision

if(k < -3) ...

where k was an unsigned type (size_t, to be specific), and that
formulation fit rather naturally into the rest of the code, given
the particular circumstances. Such circumstances however are
unusual to say the least and much more often the exception than
the rule.

Gareth Owen

unread,
Nov 22, 2016, 2:26:36 PM11/22/16
to
Tim Rentsch <t...@alumni.caltech.edu> writes:

>> No, but
>>
>> if(str1.length()-str2.length() < 12) { ... }
>>
>> has equally bizarre behaviour.
>
> It does, for slightly different reasons. But it's easy to remedy
> that problem:
>
> if(str1.length() < str2.length()+12) { ... }

Well, yes. But it'd be nice if those two thing were functionally the
same. (At least for values of .length() that commonly occur in programs,
i.e. less than SIZE_MAX / 2)

Tim Rentsch

unread,
Nov 23, 2016, 12:37:24 PM11/23/16
to
I hear ya. I think the key thing about unsigned types is that
how they behave doesn't match the unconscious expectations
people have for signed types. The two sets are just different.
IME it isn't hard to make the adjustment once one realizes
that different logical rules (ie, for how to write expressions)
are needed in the two cases.

By the way, if you wanted to use the subtraction form but still
get correct answers for the domain mentioned, we can do that by
shifting the offset, thusly:

if(str1.length()-str2.length() + SIZE_MAX/2 < 12+SIZE_MAX/2) { ... }

I wouldn't advocate writing this particular expression in this
form, but I think the general pattern is a good one to know.
0 new messages