Rant: Date and Time fall short of simplicity in D

Artur Skawina art.08.09 at gmail.com
Sat Mar 30 01:15:24 PDT 2013


On 03/30/13 07:12, Jonathan M Davis wrote:
> On Friday, March 29, 2013 22:46:27 Steven Schveighoffer wrote:
>> The issue is when you think you are invoking the opCast operator, but you
>> inadvertently end up casting using the compiler's type-bypassing version.
>> I agree the opCast call is safe, it's that its name coincides with the
>> "throw all typechecks away" operator.
> 
> I'd have to experiment to see exactly what is and isn't accepted, but in my 
> experience, the compiler rarely allows casting to or from structs without 
> opCast (the same with classes except for the inheritance tree). So, I really 
> don't think that there's much risk of accidentally using a cast on a user-
> defined type and have it use the built-in cast operator.
> 
>> I don't think to should ignore opCast, or not use it, but there should be
>> a way to hook 'to' without using opCast.  And most types should prefer
>> that.
> 
> I really just don't see a problem here. If opCast is defined, it's perfectly 
> safe regardless of what would happen if you tried to cast without opCast being 
> defined. It's also the language-defined way to do type conversions. And I really 
> don't see any need to use anything else to make std.conv.to work. By using 
> opCast, there's a standard way to define type conversion, and there's a 
> standard way for it to hook into std.conv.to, which seems way better to me 
> than trying to support every which way that a particular programmer wants to 
> try and define a conversion function. Clearly, you think that using opCast is a 
> problem, but I just don't agree. It's safe; it's standard; and it works.

   struct S {
      ubyte[] p;
   }

   import std.stdio;

   void main() {
      immutable a = S(null);
      // ...
      auto b = cast(S)a;
      writeln(typeof(a.p).stringof);
      writeln(typeof(b.p).stringof);
   }

which can easily happen in generic code. And you can't tell w/o looking
at the S implementation whether it's safe or not (with an appropriate
opCast it could be).

'cast()' is special, so you can't even use a "safer" opCast like

   auto opCast(DT)() inout { return inout(DT)(this.tupleof); }
   // or, more likely, returning some templated object instance

because a different return type is not accepted. Using a method

      auto b = a.opCast!S();

avoids these problems -- you only have to provide a correct a.opCast
implementation and the compiler will then catch caller mistakes.

'cast' /is/ dangerous, separating the safe operations from the
potentially unsafe ones is desirable. Most of the bugs caused by
mistakenly dropping 'const' etc wouldn't have happened if the explicit
casts weren't there - because the compiler would have complained,
forcing the coder to consider if the conversion really is necessary
and how to handle it properly.

artur


More information about the Digitalmars-d mailing list