Differences From Artifact [cc1b586b87325960]:
- File        
tricks/tricks.d
- 2010-11-23 09:36:27 - part of checkin [b97bd4f713] on branch trunk - automatic AST to table encoder (user: kinaba) [annotate]
 
To Artifact [00969146488cc3dc]:
- File        
tricks/tricks.d
- 2010-11-24 17:44:58 - part of checkin [b993a8ad16] on branch trunk - auto memo and re-run feature of non @value/@macro layers re-re-re-implemented. (user: kinaba) [annotate]
 
    95     95    // shiyo- desu. Don't use in this way.
    96     96    //   Tamp tries to call new Tomp(real) (because it only sees Tomp's members),
    97     97    //   but it fails because Tomp takes (int,string,real).
    98     98    assert( !__traits(compiles, {
    99     99     class Tamp : Tomp { mixin SimpleConstructor; }
   100    100    }) );
   101    101   }
          102  +
          103  +hash_t structuralHash(T)(T x)
          104  +{
          105  + alias SC_Unqual!(T) UCT;
          106  +
          107  + static if(is(UCT == class))
          108  +  return (cast(UCT)x).toHash();
          109  + else
          110  + static if(SC_HasGoodHash!(UCT))
          111  +  { return typeid(UCT).getHash(&x); }
          112  + else
          113  + static if(is(UCT T == T[]))
          114  +  { hash_t h; foreach(e; x) h+=structuralHash(e); return h; }
          115  + else
          116  + static if(is(UCT == struct))
          117  +  static if(__traits(compiles, std.bigint.BigInt))
          118  +   static if(is(UCT == std.bigint.BigInt))
          119  +    return cast(hash_t) x.toInt();
          120  +   else
          121  +    static assert(false, "should not use struct.toHash");
          122  +  else
          123  +   static assert(false, "should not use struct.toHash");
          124  + else
          125  +  static assert(false, "nonhashable datatype "~UCT.stringof);
          126  +}
          127  +
          128  +alias std.traits.Unqual SC_Unqual;
          129  +
          130  +template SC_HasGoodHash(T)
          131  +{
          132  + enum SC_HasGoodHash =
          133  +  is(T : bool) || isNumeric!(T) || isSomeString!(T) || isSomeChar!(T) || isPointer!(T);
          134  +}
   102    135   
   103    136   /// Mixing-in the MOST-DERIVED-member-wise comparator for a class
          137  +/// BE SURE THAT THIS IS CONSISTENT WITH opCmp and opEquals
   104    138   
   105    139   template SimpleToHash()
   106    140   {
   107    141    override hash_t toHash() const /// member-by-member hash
   108    142    {
   109    143     hash_t h = 0;
   110    144     foreach(mem; this.tupleof)
   111         -   h += typeid(mem).getHash(&mem);
          145  +   h += structuralHash(mem);
   112    146     return h;
   113    147    }
   114    148   }
          149  +
          150  +/// Mixing-in the MOST-DERIVED-member-wise comparator for a class
          151  +
          152  +template SimpleCompareWithoutToHash()
          153  +{
          154  + override bool opEquals(Object rhs) const /// member-by-member equality
          155  + {
          156  +  return opCmp(rhs) == 0;
          157  + }
          158  +
          159  + override int opCmp(Object rhs_) const /// member-by-member compare
          160  + {
          161  +  if( rhs_ is null )
          162  +   return -1;
          163  +  if( auto rhs = cast(typeof(this))rhs_ )
          164  +  {
          165  +   foreach(i,_; this.tupleof)
          166  +   {
          167  +    static if(is(typeof(_) == struct))
          168  +     auto c = (cast(SC_Unqual!(typeof(_)))this.tupleof[i]).opCmp(rhs.tupleof[i]);
          169  +    else
          170  +     auto c = typeid(_).compare(&this.tupleof[i],&rhs.tupleof[i]);
          171  +    if(c)
          172  +     return c;
          173  +   }
          174  +   return 0;
          175  +  }
          176  +  return typeid(this).opCmp(typeid(rhs_));
          177  + }
          178  +}
   115    179   
   116    180   /// Mixing-in the MOST-DERIVED-member-wise comparator for a class
   117    181   
   118    182   /*mixin*/
   119    183   template SimpleCompare()
   120    184   {
   121         - override bool opEquals(Object rhs_) const /// member-by-member equality
   122         - {
   123         -  if( auto rhs = cast(typeof(this))rhs_ )
   124         -  {
   125         -   foreach(i,_; this.tupleof)
   126         -    if( this.tupleof[i] != (cast(const)rhs).tupleof[i] )
   127         -     return false;
   128         -   return true;
   129         -  }
   130         -  assert(false, sprintf!"Cannot compare %s with %s"(typeid(this), typeid(rhs_)));
   131         - }
   132         -
   133    185    mixin SimpleToHash;
   134         -
   135         - override int opCmp(Object rhs_) const /// member-by-member compare
   136         - {
   137         -  if( auto rhs = cast(typeof(this))rhs_ )
   138         -  {
   139         -   foreach(i,_; this.tupleof)
   140         -    if( this.tupleof[i] != (cast(const)rhs).tupleof[i] ) {
   141         -     auto a = (cast(SC_Unqual!(typeof(this)))this).tupleof[i];
   142         -     auto b =  rhs.tupleof[i];
   143         -     return a < b ? -1 : +1;
   144         -    }
   145         -// not work well for structures???????
   146         -//    if(auto c = typeid(_).compare(&this.tupleof[i],&rhs.tupleof[i]))
   147         -//     return c;
   148         -   return 0;
   149         -  }
   150         -  assert(false, sprintf!"Cannot compare %s with %s"(typeid(this), typeid(rhs_)));
   151         - }
          186  + mixin SimpleCompareWithoutToHash;
   152    187   }
   153    188   
   154         -alias std.traits.Unqual SC_Unqual;
   155         -
   156    189   unittest
   157    190   {
   158    191    class Temp
   159    192    {
   160    193     int x;
   161    194     string y;
   162    195     mixin SimpleConstructor;
................................................................................
   173    206    class TempDummy
   174    207    {
   175    208     int x;
   176    209     string y;
   177    210     mixin SimpleConstructor;
   178    211     mixin SimpleCompare;
   179    212    }
   180         - assert_throw!AssertError( new Temp(1,"foo") == new TempDummy(1,"foo") );
   181         - assert_throw!AssertError( new Temp(1,"foo") <= new TempDummy(1,"foo") );
          213  + assert_ne( new Temp(1,"foo"), new TempDummy(1,"foo") );
          214  + assert_nothrow( new Temp(1,"foo") <= new TempDummy(1,"foo") );
   182    215   }
   183    216   
   184    217   /// Mixing-in a simple toString method
   185    218   
   186    219   /*mixin*/
   187    220   template SimpleToString()
   188    221   {
................................................................................
   222    255   template SimpleClass()
   223    256   {
   224    257    mixin SimpleConstructor;
   225    258    mixin SimpleCompare;
   226    259    mixin SimpleToString;
   227    260   }
   228    261   
   229         -/// Will be used for dynamic overload resolution pattern
          262  +/// Utility
   230    263   
   231    264   template firstParam(T)
   232    265   {
   233    266    alias ParameterTypeTuple!(T)[0] firstParam;
   234    267   }