From Asbjørn, 7 Years ago, written in Delphi (Object Pascal).
Embed
  1. program TupleTest;
  2.  
  3. {$APPTYPE CONSOLE}
  4.  
  5. uses
  6.   System.SysUtils;
  7.  
  8. type
  9.   IgnoreElm = record end;
  10.  
  11.   Tuple<T1, T2> = record
  12.   {$REGION 'Implementation details'}
  13.   private
  14.     type
  15.       P1 = ^T1;
  16.       P2 = ^T2;
  17.       Tier = record
  18.         Ref1: P1;
  19.         Ref2: P2;
  20.  
  21.         class operator LessThanOrEqual(const Dest: Tier; const Src: Tuple<T1, T2>): boolean; overload;
  22.       end;
  23.   private
  24.     class operator Implicit(const Value: Tuple<T1, T2>): Tuple<T1, IgnoreElm>;
  25.     class operator Implicit(const Value: Tuple<T1, T2>): Tuple<IgnoreElm, T2>;
  26.   {$ENDREGION}
  27.   public
  28.     Elm1: T1;
  29.     Elm2: T2;
  30.   end;
  31.  
  32.   Tuple = record
  33.   public
  34.     class function From<T1, T2>(const Value1: T1; Value2: T2): Tuple<T1, T2>; static;
  35.     class function Tie<T1, T2>(var Elm1: T1; var Elm2: T2): Tuple<T1, T2>.Tier; overload; static;
  36.     class function Tie<T1>(var Elm1: T1; const Ignored2: IgnoreElm): Tuple<T1, IgnoreElm>.Tier; overload; static;
  37.     class function Tie<T2>(const Ignored1: IgnoreElm; var Elm2: T2): Tuple<IgnoreElm, T2>.Tier; overload; static;
  38.   end;
  39.  
  40. const
  41.   Ignore: IgnoreElm = ();
  42.  
  43. procedure Test;
  44. var
  45.   tup: Tuple<integer, string>;
  46.   i: integer;
  47.   s: string;
  48. begin
  49.   i := 123;
  50.   s := 'bar';
  51.  
  52.   tup := Tuple.From<integer, string>(42, 'foo');
  53.  
  54.   Tuple.Tie(Ignore, s) <= tup;
  55.  
  56.   WriteLn(i, ', ', s);  // 123, foo
  57. end;
  58.  
  59. { Tuple }
  60.  
  61. class function Tuple.From<T1, T2>(const Value1: T1; Value2: T2): Tuple<T1, T2>;
  62. begin
  63.   result.Elm1 := Value1;
  64.   result.Elm2 := Value2;
  65. end;
  66.  
  67. class function Tuple.Tie<T1, T2>(var Elm1: T1; var Elm2: T2): Tuple<T1, T2>.Tier;
  68. begin
  69.   result.Ref1 := @Elm1;
  70.   result.Ref2 := @Elm2;
  71. end;
  72.  
  73. class function Tuple.Tie<T1>(var Elm1: T1;
  74.   const Ignored2: IgnoreElm): Tuple<T1, IgnoreElm>.Tier;
  75. begin
  76.   result.Ref1 := @Elm1;
  77.   result.Ref2 := nil;
  78. end;
  79.  
  80. class function Tuple.Tie<T2>(const Ignored1: IgnoreElm;
  81.   var Elm2: T2): Tuple<IgnoreElm, T2>.Tier;
  82. begin
  83.   result.Ref1 := nil;
  84.   result.Ref2 := @Elm2;
  85. end;
  86.  
  87. { Tuple<T1, T2>.Tier }
  88.  
  89. class operator Tuple<T1, T2>.Tier.LessThanOrEqual(const Dest: Tier;
  90.   const Src: Tuple<T1, T2>): boolean;
  91. begin
  92.   if (TypeInfo(T1) <> TypeInfo(IgnoreElm)) then
  93.     Dest.Ref1^ := Src.Elm1;
  94.   if (TypeInfo(T2) <> TypeInfo(IgnoreElm)) then
  95.     Dest.Ref2^ := Src.Elm2;
  96.   result := True;
  97. end;
  98.  
  99. { Tuple<T1, T2> }
  100.  
  101. class operator Tuple<T1, T2>.Implicit(
  102.   const Value: Tuple<T1, T2>): Tuple<T1, IgnoreElm>;
  103. begin
  104.   result.Elm1 := Value.Elm1;
  105. end;
  106.  
  107. class operator Tuple<T1, T2>.Implicit(
  108.   const Value: Tuple<T1, T2>): Tuple<IgnoreElm, T2>;
  109. begin
  110.   result.Elm2 := Value.Elm2;
  111. end;
  112.  
  113. begin
  114.   Test;
  115.   ReadLn;
  116. end.
  117.