Topic: n < 0 versus v < T(0)


Author: "Fernando Cacciola" <fcacciola@fibertel.com.ar>
Date: 2000/07/11
Raw View
Bill Wade <bill.wade@stoner.com> escribi=F3 en el mensaje de noticias
8k57ib$ti0@library2.airnews.net...
>
> "Fernando Cacciola" <fcacciola@fibertel.com.ar> wrote
>
> > > > (A)  n < 0
> > > > (B)  n < T(0)
>
> > I concluded that expression B is at least as safe and efficient than =
A,
>
> If (B) compiles and (A) doesn't, a likely cause is that T's author made
this
> particular constructor explicit.  If that is the case it is almost cert=
ain
> that T's author thought that the conversion was dangerous.  If (B) does
> something that (A) doesn't, and T's author believes that particular
> something is dangerous, how can you reach the conclusion that (B) is as
safe
> as (A)?
I was obviously out of context.
I decline to assert that IN GENERAL, but I keep asserting it in the
particular case of GENERIC PROGRAMMING IN CONTEXT( that is, when T is
bounded with a set of requirements, such as being a numeric -at most user
defined- type)
I'm intending to set up rules for generic programming, and in particular =
to
the field of numerical and geometric computations.
The expressions I showed are supposed to have semantic meaning, that is,
they are supposed to be part of a template code which is supposed to be
usable with types having some semantic properties. In particular, T is
supposed to be a numeric type (or as closed as that as it can be).
I'll get back on this at the end of this article.

>
> Even in the absence of explicit constructors (B) is more dangerous.
> Consider:
>
>   std::string n;
>   n < 0;    // Requires a diagnostic
>   n < std::string(0); // Undefined behaviour
>
The error here is that the template user shouldn't use std::string to
instantiate it.


> > but support more cases, so that form should be used for generic
> programming.
>
> The cast makes the code less generic.  For a large-integer class it is
> likely that both
>
>   bool operator<(const BigInt&, int);
>   bool operator<(const BigInt&, const BigInt&);
>
> were written, with the second form being much faster.  (B) gives the ri=
ght
> answer, but it is slower than (A).

Certainly.
As I explained above, I'm  referring to cases when T can be whatever, wit=
h
as little restrictions as possible.
When you write a piece of code which uses some Type, you know what this t=
ype
is and what it can do, so you can take advantage of particular constructs
and operations, and you can write expressions the right way.
However, when you write generic code, you don't know what T is, and the b=
est
you can do is to make sure that the user understands the requirements for=
 T,
but also to write expressions which are more likely to work.
This always involves a trade-off between efficiency and flexibility. For
example,
the expression: n < 0 is better for BigInt, but is a source of ambiguitie=
s
for most other cases. This is what I'm trying to show here.

Fernando Cacciola
Sierra s.r.l.
fcacciola@fibertel.com.ar
www.gosierra.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 2000/07/12
Raw View
Fernando Cacciola wrote:
> In article <newscache$luk4xf$bbi$1@lnews.actcom.co.il>,
>   "Daniel M. Pfeffer" <pfefferd@nospam.internet-zahav.net> wrote:

[...]

> > If T has both, expression A may be ambiguous (I'm unsure about the
> > conversion precedence rules in this case).
> Yes.
> Most user defined number arithmetic types I've seen and wrote have both,
> but now I'm wondering if this is a good idea. Perhaps explicit constructors
> along with conversion operators are the best way. What do you think?

I'd say this depends. If the type is a high precision float
(i.e. higher precision than any built-in floating point type),
I'd prefer the (value preserving) conversion _to_ the class
to be implicit (non-explicit constructor) and the (precision
loss) conversion _from_ the class to be explicit (normal
member function instead of conversion operator).


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Fernando Cacciola" <fcacciola@fibertel.com.ar>
Date: 2000/07/12
Raw View
Christopher Eltschka <celtschk@physik.tu-muenchen.de> wrote:

>> > If T has both, expression A may be ambiguous (I'm unsure about the
>> > conversion precedence rules in this case).
>> Yes.
>> Most user defined number arithmetic types I've seen and wrote have both,
>> but now I'm wondering if this is a good idea. Perhaps explicit
constructors
>> along with conversion operators are the best way. What do you think?
>
>I'd say this depends. If the type is a high precision float
>(i.e. higher precision than any built-in floating point type),
>I'd prefer the (value preserving) conversion _to_ the class
>to be implicit (non-explicit constructor) and the (precision
>loss) conversion _from_ the class to be explicit (normal
>member function instead of conversion operator).
Certainly.
It seems clear that at least one way should be more restrictive.
This design (non-explicit constructor and conversion member function -not
operator-) seems more appropriate.
Thanks.


Fernando Cacciola
Sierra s.r.l.
fcacciola@fibertel.com.ar
www.gosierra.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: James Kuyper <kuyper@wizard.net>
Date: 2000/07/08
Raw View
Fernando Cacciola wrote:
>
> In article <newscache$luk4xf$bbi$1@lnews.actcom.co.il>,
>   "Daniel M. Pfeffer" <pfefferd@nospam.internet-zahav.net> wrote:
> [snip]
> > > (A)  n < 0
> > > (B)  n < T(0)
....
> > Expressions A and B differ in that expression A allows n to be converted
> to
> > 'int', rather than constructing a T object from 0. This may occur when T
> has
> > no non-explicit constructor accepting an 'int', but has an 'operator
> int()'.
> > If T has both, expression A may be ambiguous (I'm unsure about the
> > conversion precedence rules in this case).
> Yes.
> Most user defined number arithmetic types I've seen and wrote have both,
> but now I'm wondering if this is a good idea. Perhaps explicit constructors
> along with conversion operators are the best way. What do you think?

Definitely! Ambiguity is dangerous; 'explicit' is there for precisely
this purpose.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Fernando Cacciola" <fcacciola@fibertel.com.ar>
Date: 2000/07/09
Raw View
----- Original Message -----
From: Nicola Musatti <objectway@divalsim.it>
Newsgroups: comp.std.c++
Sent: Saturday, July 08, 2000 6:27 AM
Subject: Re: n < 0 versus v < T(0)



> I've been badly hit by this using Borland's C++ Builder and its Currency
> class. If you have
>
> Currency n = 1.5;
> Currency m = true ? n : 0;
>
> m is now 1 !
>
> I always make sure that both expressions around the colon are of exactly
> the same type.

Interesting....

I've tested this using a custom class and found out that 'n' is converted to
int since the second operand is int.
What surprises me is that MyClass has both:

   MyClass(  T const & ) ;
   operator T();

This is subtle, because in other contexts an ambiguity ocurrs, for example,
if the expression were:

  bool less = n < 0 ;

The compiler is allowed to convert either operand, so ambiguity ocurrs.

According to what I can intrepret out of the Standard:

  If the operator can be overloaded (such as '<') then either operand can be
converted (so the constructor or the conversion operators can be used); but
 If the operator cannot be overloaded (such as '?'), then in precense of a
built-in type the other operand is converted. This can be resolved only by
explictely casting both operands as you suggested (unless the conversion to
built-in is ok)

Thanks for pointing this out.

Fernando Cacciola
Sierra s.r.l.
fcacciola@fibertel.com.ar
www.gosierra.com


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Bill Wade" <bill.wade@stoner.com>
Date: 2000/07/09
Raw View
"Fernando Cacciola" <fcacciola@fibertel.com.ar> wrote

> > > (A)  n < 0
> > > (B)  n < T(0)

> I concluded that expression B is at least as safe and efficient than A,

If (B) compiles and (A) doesn't, a likely cause is that T's author made this
particular constructor explicit.  If that is the case it is almost certain
that T's author thought that the conversion was dangerous.  If (B) does
something that (A) doesn't, and T's author believes that particular
something is dangerous, how can you reach the conclusion that (B) is as safe
as (A)?

Even in the absence of explicit constructors (B) is more dangerous.
Consider:

  std::string n;
  n < 0;    // Requires a diagnostic
  n < std::string(0); // Undefined behavior

> but support more cases, so that form should be used for generic
programming.

The cast makes the code less generic.  For a large-integer class it is
likely that both

  bool operator<(const BigInt&, int);
  bool operator<(const BigInt&, const BigInt&);

were written, with the second form being much faster.  (B) gives the right
answer, but it is slower than (A).


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Fernando Cacciola" <fcacciola@fibertel.com.ar>
Date: 2000/07/08
Raw View
In article <newscache$luk4xf$bbi$1@lnews.actcom.co.il>,
  "Daniel M. Pfeffer" <pfefferd@nospam.internet-zahav.net> wrote:
[snip]
> > (A)  n < 0
> > (B)  n < T(0)
> > (C)  n < (T)0
[snip]
> > 1) T is int (or other built-in integer type).
> > 2) T is double (or other built-in floating point type)
> > 3) T is a user defined type with a single non-explicit constructor for
> > int.
> > 4) T is a user defined type with a single explicit constructor for int.
> > 5) T is a user defined type with a single non-explicit constructor for
> > double.
> > 6) T is a user defined type with a single explicit constructor for
> > double.
> >

> Expression C uses an old-style cast, which should be converted to one of
the
> new-style casts. The only case where it is not functionally equivalent to
> expression B is when type T has no constructor that accepts 0 as a
> parameter, which means that you must use some variant of
> reinterpret_cast<T>() for the conversion. In other words, the code is
> unsafe!
Agreed.


> Expressions A and B differ in that expression A allows n to be converted
to
> 'int', rather than constructing a T object from 0. This may occur when T
has
> no non-explicit constructor accepting an 'int', but has an 'operator
int()'.
> If T has both, expression A may be ambiguous (I'm unsure about the
> conversion precedence rules in this case).
Yes.
Most user defined number arithmetic types I've seen and wrote have both,
but now I'm wondering if this is a good idea. Perhaps explicit constructors
along with conversion operators are the best way. What do you think?

>
> To answer your questions:
>
> 1. both are equally correct.
> 2. both are equally correct
> 3. both are equally correct.
> 4. only B is correct. (assuming T doesn't contain an implicit conversion
to
> 'int')
> 5. both are equally correct. (if a constructor for another arithmetic type
> other than 'int' exists, they may be ambiguous)
> 6. only B is correct. (if a constructor for another arithmetic type other
> than 'int' exists, it may be ambiguous)
>
> I would agree with your assertion that expression B is the only reliable
> form for template code.

Thanks for your answers.
I concluded that expression B is at least as safe and efficient than A, but
support more cases, so that form should be used for generic programming.

Thanks.


Fernando Cacciola
Sierra s.r.l.
fcacciola@fibertel.com.ar
www.gosierra.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Nicola Musatti <objectway@divalsim.it>
Date: 2000/07/08
Raw View

Fernando Luis Cacciola Carballal wrote:
[...]
>   expr ? n : 0 ; // I believe this should be ok.

I've been badly hit by this using Borland's C++ Builder and its Currency
class. If you have

Currency n = 1.5;
Currency m = true ? n : 0;

m is now 1 !

I always make sure that both expressions around the colon are of exactly
the same type.

Best regards,
Nicola Musatti

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Fernando Luis Cacciola Carballal <fcacciola@fibertel.com.ar>
Date: 2000/06/30
Raw View

Hi all,

Given the following 3 expressions (assuming n is of type T):

(A)  n < 0
(B)  n < T(0)
(C)  n < (T)0

Which one is more correct considering the following posible cases:

1) T is int (or other built-in integer type).
2) T is double (or other built-in floating point type)
3) T is a user defined type with a single non-explicit constructor for
int.
4) T is a user defined type with a single explicit constructor for int.
5) T is a user defined type with a single non-explicit constructor for
double.
6) T is a user defined type with a single explicit constructor for
double.

I'm trying to consider different situations were literals (which are of
type int
or double) are mixed with other types.
I support the assertion that the expression of the form (B) should
be the only one used for generic code involving literals (since T is
unknown).

How about similar situations, like:

  n + 1 ;  // should be + T(1)?

  expr ? n : 0 ; // I believe this should be ok.

  non-template binfunc(n,0) ; // This one is ok if the signature avoid
ambiguities.

  template binfunc(n,0) ;  // This should have T(0) to prroperly
resolve the template.

--
Fernando Luis Cacciola Carballal
Sierra s.r.l.
fcacciola@fibertel.com.ar
www.gosierra.com


Sent via Deja.com http://www.deja.com/
Before you buy.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Daniel M. Pfeffer" <pfefferd@nospam.internet-zahav.net>
Date: 2000/07/04
Raw View
"Fernando Luis Cacciola Carballal" <fcacciola@fibertel.com.ar> wrote in
message news:8jg9t5$r3n$1@nnrp1.deja.com...
>
>
> Hi all,
>
> Given the following 3 expressions (assuming n is of type T):
>
> (A)  n < 0
> (B)  n < T(0)
> (C)  n < (T)0
>
> Which one is more correct considering the following posible cases:
>
> 1) T is int (or other built-in integer type).
> 2) T is double (or other built-in floating point type)
> 3) T is a user defined type with a single non-explicit constructor for
> int.
> 4) T is a user defined type with a single explicit constructor for int.
> 5) T is a user defined type with a single non-explicit constructor for
> double.
> 6) T is a user defined type with a single explicit constructor for
> double.
>
> I'm trying to consider different situations were literals (which are of
> type int
> or double) are mixed with other types.
> I support the assertion that the expression of the form (B) should
> be the only one used for generic code involving literals (since T is
> unknown).
>
> How about similar situations, like:
>
>   n + 1 ;  // should be + T(1)?
>
>   expr ? n : 0 ; // I believe this should be ok.
>
>   non-template binfunc(n,0) ; // This one is ok if the signature avoid
> ambiguities.
>
>   template binfunc(n,0) ;  // This should have T(0) to prroperly
> resolve the template.

Expression C uses an old-style cast, which should be converted to one of the
new-style casts. The only case where it is not functionally equivalent to
expression B is when type T has no constructor that accepts 0 as a
parameter, which means that you must use some variant of
reinterpret_cast<T>() for the conversion. In other words, the code is
unsafe!

Expressions A and B differ in that expression A allows n to be converted to
'int', rather than constructing a T object from 0. This may occur when T has
no non-explicit constructor accepting an 'int', but has an 'operator int()'.
If T has both, expression A may be ambiguous (I'm unsure about the
conversion precedence rules in this case).

To answer your questions:

1. both are equally correct.
2. both are equally correct
3. both are equally correct.
4. only B is correct. (assuming T doesn't contain an implicit conversion to
'int')
5. both are equally correct. (if a constructor for another arithmetic type
other than 'int' exists, they may be ambiguous)
6. only B is correct. (if a constructor for another arithmetic type other
than 'int' exists, it may be ambiguous)

I would agree with your assertion that expression B is the only reliable
form for template code.


Daniel Pfeffer


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]