www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Disable implicit conversion

reply Eugene <yes9111 gmail.com> writes:
Hi!

What I want to do is pretty simple.  I need to subtract a ubyte from a
ubyte and store the result in a ubyte.  The problem is that DMD
implicitly wants to convert the ubytes into an integer, so it fails
when attempting to store the result into a ubyte.  (Int cannot be
converted to ubyte?)
The error message I get:

src\test.d(26): Error: cannot implicitly convert expression
(cast(int)u2 - cast(int)u1) of type int to ubyte
Mar 07 2011
next sibling parent "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> writes:
On Mon, 07 Mar 2011 10:33:28 +0000, Eugene wrote:

 Hi!
 
 What I want to do is pretty simple.  I need to subtract a ubyte from a
 ubyte and store the result in a ubyte.  The problem is that DMD
 implicitly wants to convert the ubytes into an integer, so it fails when
 attempting to store the result into a ubyte.  (Int cannot be converted
 to ubyte?)
 The error message I get:
 
 src\test.d(26): Error: cannot implicitly convert expression (cast(int)u2
 - cast(int)u1) of type int to ubyte
DMD is simply trying to protect you from what is otherwise a common bug. As a general rule, the result of an integer subtraction should be stored in a signed integer, since the result may be negative. If you are 100% sure that u2 >= u1, or if integer wraparound is what you're after, just use a cast: auto result = cast(ubyte)(u2 - u1); -Lars
Mar 07 2011
prev sibling next sibling parent reply KennyTM~ <kennytm gmail.com> writes:
On Mar 7, 11 18:33, Eugene wrote:
 Hi!

 What I want to do is pretty simple.  I need to subtract a ubyte from a
 ubyte and store the result in a ubyte.  The problem is that DMD
 implicitly wants to convert the ubytes into an integer, so it fails
 when attempting to store the result into a ubyte.  (Int cannot be
 converted to ubyte?)
 The error message I get:

 src\test.d(26): Error: cannot implicitly convert expression
 (cast(int)u2 - cast(int)u1) of type int to ubyte
ubyte u3 = (u2 - u1) & 0xff; // ^^^^^^ // make sure the result fall in ubyte's value range
Mar 07 2011
parent reply Jesse Phillips <jessekphillips+D gmail.com> writes:
KennyTM~ Wrote:

 On Mar 7, 11 18:33, Eugene wrote:
 Hi!

 What I want to do is pretty simple.  I need to subtract a ubyte from a
 ubyte and store the result in a ubyte.  The problem is that DMD
 implicitly wants to convert the ubytes into an integer, so it fails
 when attempting to store the result into a ubyte.  (Int cannot be
 converted to ubyte?)
 The error message I get:

 src\test.d(26): Error: cannot implicitly convert expression
 (cast(int)u2 - cast(int)u1) of type int to ubyte
ubyte u3 = (u2 - u1) & 0xff; // ^^^^^^ // make sure the result fall in ubyte's value range
I recommend against this for a number of reasons. For one this removes an explicit cast which makes it harder to find for review (one of the reasons for cast() instead of (). Not only that but the operation isn't any safer than a cast, if overflow didn't matter and you just need it to fit then this would be good. Lastly overflow does matter and if it happens the code will continue to silently work. I recommend using std.conv.to because it will throw an exception if an overflow were to happen.
Mar 07 2011
next sibling parent Stewart Gordon <smjg_1998 yahoo.com> writes:
On 07/03/2011 16:40, Jesse Phillips wrote:
 KennyTM~ Wrote:

 On Mar 7, 11 18:33, Eugene wrote:
 Hi!

 What I want to do is pretty simple.  I need to subtract a ubyte from a
 ubyte and store the result in a ubyte.  The problem is that DMD
 implicitly wants to convert the ubytes into an integer, so it fails
 when attempting to store the result into a ubyte.  (Int cannot be
 converted to ubyte?)
I've been bitten by that annoyance while doing Java stuff in the past. http://d.puremagic.com/issues/show_bug.cgi?id=1977 <snip>
 Not only that but the operation isn't any safer than a cast, if overflow
didn't matter
 and you just need it to fit then this would be good.

 Lastly overflow does matter and if it happens the code will continue to
silently work.
 I recommend using std.conv.to because it will throw an exception if an
overflow were to
 happen.
If overflow of a ubyte matters, surely so does overflow of an int or long? In the OP's case, the only possible overflow is a negative result. As such, if overflow matters, one will do something like if (u2 < u1) { // ... } else { u3 = cast(ubyte) (u2 - u1); } For such simple cases as this, using a library function to convert an overflow into an exception might be overkill. Stewart.
Mar 07 2011
prev sibling next sibling parent spir <denis.spir gmail.com> writes:
On 03/07/2011 05:40 PM, Jesse Phillips wrote:
 KennyTM~ Wrote:

 On Mar 7, 11 18:33, Eugene wrote:
 Hi!

 What I want to do is pretty simple.  I need to subtract a ubyte from a
 ubyte and store the result in a ubyte.  The problem is that DMD
 implicitly wants to convert the ubytes into an integer, so it fails
 when attempting to store the result into a ubyte.  (Int cannot be
 converted to ubyte?)
 The error message I get:

 src\test.d(26): Error: cannot implicitly convert expression
 (cast(int)u2 - cast(int)u1) of type int to ubyte
ubyte u3 = (u2 - u1)& 0xff; // ^^^^^^ // make sure the result fall in ubyte's value range
I recommend against this for a number of reasons. For one this removes an explicit cast which makes it harder to find for review (one of the reasons for cast() instead of (). Not only that but the operation isn't any safer than a cast, if overflow didn't matter and you just need it to fit then this would be good. Lastly overflow does matter and if it happens the code will continue to silently work. I recommend using std.conv.to because it will throw an exception if an overflow were to happen.
I agree. Then, why do we still have cast? Denis -- _________________ vita es estrany spir.wikidot.com
Mar 07 2011
prev sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Monday, March 07, 2011 12:10:07 spir wrote:
 On 03/07/2011 05:40 PM, Jesse Phillips wrote:
 KennyTM~ Wrote:
 On Mar 7, 11 18:33, Eugene wrote:
 Hi!
 
 What I want to do is pretty simple.  I need to subtract a ubyte from a
 ubyte and store the result in a ubyte.  The problem is that DMD
 implicitly wants to convert the ubytes into an integer, so it fails
 when attempting to store the result into a ubyte.  (Int cannot be
 converted to ubyte?)
 The error message I get:
 
 src\test.d(26): Error: cannot implicitly convert expression
 (cast(int)u2 - cast(int)u1) of type int to ubyte
ubyte u3 = (u2 - u1)& 0xff; // ^^^^^^ // make sure the result fall in ubyte's value range
I recommend against this for a number of reasons. For one this removes an explicit cast which makes it harder to find for review (one of the reasons for cast() instead of (). Not only that but the operation isn't any safer than a cast, if overflow didn't matter and you just need it to fit then this would be good. Lastly overflow does matter and if it happens the code will continue to silently work. I recommend using std.conv.to because it will throw an exception if an overflow were to happen.
I agree. Then, why do we still have cast?
D is a systems language. It's supposed to let you do low level stuff like write kernel. Casts are required in such an environment, so it's not like we can't _not_ have them in the language, and in many cases, std.conv.to just casts anyway. So, while it might be best practice to prefer std.conv.to to casting, we still need casts in the language. - Jonathan M Davis
Mar 07 2011
parent reply Eugene <yes9111 gmail.com> writes:
So the resulting output will cast both ubytes into integers and then
cast that into a ubyte?
Mar 08 2011
parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 08 Mar 2011 05:19:31 -0500, Eugene <yes9111 gmail.com> wrote:

 So the resulting output will cast both ubytes into integers and then
 cast that into a ubyte?
All arithmetic in the CPU is done on an integer level anyways. So the language is just reflecting what the architecture does. -Steve
Mar 08 2011
prev sibling parent Jesse Phillips <jessekphillips+D gmail.com> writes:
Stewart Gordon Wrote:

 If overflow of a ubyte matters, surely so does overflow of an int or long?
 
 In the OP's case, the only possible overflow is a negative result.  As such,
if overflow 
 matters, one will do something like
 
      if (u2 < u1) {
          // ...
      } else {
          u3 = cast(ubyte) (u2 - u1);
      }
 
 For such simple cases as this, using a library function to convert an overflow
into an 
 exception might be overkill.
 
 Stewart.
By matters I meant that you do not expect it to result in a negative number, but if it does the code will start operating incorrectly. There are cases where you may expect the result to go negative but don't care as it won't effect what you are doing (I don't actually have any examples of this but it is possible). My main point is that if you are in the habit of using std.conv.to instead of casting then you are more likely to get a meaningful message at run-time then a program in invalid state. But you are correct that if you desire doing something with what would be an Exception then writing the explicit code is better.
Mar 07 2011