January 15, 2009
Sergey Gromov wrote:
> Sun, 11 Jan 2009 18:09:15 -0800, Charles Hixson wrote:
> 
>> Well, my use case just involves being able to use library function with the proper base type.  (I.e., int instead of long or byte when I do
>> typedef int LocalType;
>> LocalType t;
>> File f;
>> f.write(t);
>>
>> I'll grant that I *can* use alias for such a purpose, but that doesn't distinguish between LocalType and ArrayIndex in routines defined for those types.  E.g.:
>> typedef  int ArrayIndex;
>> void zeroIndex(out ArrayIndex ai)  {	ai = 0;  }
>> zeroIndex(t);
>>
>> Should throw an error.  If I'm using alias it doesn't (and shouldn't);
> 
> Well, I presume File.write() has many overloads, including one for int
> but none for LocalType.  When aliasing, the LocalType *is* an int, it
> matches exactly File.write(int) and the compiler is happy.
> 
> However, with a typedef, LocalType is a distinct type.  Yes it casts to
> int implicitly, but likewise it casts implicitly to char, short and
> long.  So compiler gets a whole load of File.write() functions matching
> with conversions, and fails because of the ambiguity.
> 
> That's how the language works, and it's pretty consistent IMO.  What you
> can do is:
> 
>   f.write(cast(int)t);
> 
> or use templates to generalize:
> 
>   auto fileWrite(T : LocalType)(File f, T v)
>   {
>     return f.write(cast(int)v);
>   }
>   auto fileWrite(T)(File f, T v)
>   {
>     return f.write(v);
>   }
>   fileWrite(f, t); // OK
>   fileWrite(f, 15); // OK
> 
> When we get generic function calls you'd be even able to write:
> 
>   void write(File f, LocalType l)
>   {
>     f.write(cast(int)l);
>   }
>   f.write(t); // OK, write(f, t) is called

A) Yes, it works the way that you say.  This damages it's utility.
B) I'm replying to a question as to how typedef could reasonably be extended.
January 16, 2009
Charles Hixson wrote:
> A) Yes, it works the way that you say.  This damages it's utility.
> B) I'm replying to a question as to how typedef could reasonably be extended.

The point of a typedef is to provide additional type safety. This would not exist if you could implicitly cast back and forth. Unless you want an implicit cast from a typedef type to the base type, and not the reverse -- that might be reasonable (I can't immediately see any issues with it).
January 18, 2009
Christopher Wright wrote:
> Charles Hixson wrote:
>> A) Yes, it works the way that you say.  This damages it's utility.
>> B) I'm replying to a question as to how typedef could reasonably be extended.
> 
> The point of a typedef is to provide additional type safety. This would not exist if you could implicitly cast back and forth. Unless you want an implicit cast from a typedef type to the base type, and not the reverse -- that might be reasonable (I can't immediately see any issues with it).

That's all that's needed to solve the use case that I presented. Unfortunately, what it tried to do was cast it to either byte or long rather than the base case (which was int).  Fortunately it couldn't decide which to cast it as, as either choice would have been an error. (I'm writing to a binary file, and the size of the item written is significant.)

Because of this, to avoid scattering casts throughout the program, I had to replace the typedef with alias.  This works, but it also definitely prevents the type safety that a typedef could (should) have provided.
January 18, 2009
Charles Hixson wrote:
> Unfortunately, what it tried to do was cast it to either byte or long rather than the base case (which was int).  Fortunately it couldn't decide which to cast it as, as either choice would have been an error. (I'm writing to a binary file, and the size of the item written is significant.)

The following works for me (using LDC):

typedef int mint;
void foo (long i) {}
void main ()
{
    mint a = 1;
    foo (a);
}

However, this also works:
typedef int mint;
void foo (byte i) {}
void main ()
{
    mint a = 1;
    foo (a);
}

It's an implicit narrowing conversion -- that involves data loss. This is a bug.
January 18, 2009
Christopher Wright wrote:
> It's an implicit narrowing conversion -- that involves data loss. This is a bug.

Actually, you said you had two methods, something like this:

void foo (byte i) {}
void foo (long i) {}
void main ()
{
    int a = 1;
    foo (a);
    byte b = a; // no casts
}

This example doesn't use typedefs but still complains about overloads. I find it odd that you can implicitly cast an arithmetic type of one width to another of a smaller width. I'm making a feature enhancement request for this.
January 18, 2009
Christopher Wright wrote:
> It's an implicit narrowing conversion -- that involves data loss. This is a bug.

Okay, you can compile with warnings and dmd yells at you. But that's about it. This is pretty cruddy.
1 2
Next ›   Last »