Browse Source

Adding tuple unit

Frederic Kehrein 10 months ago
parent
commit
d3b14eb1ba

+ 3 - 0
packages/rtl-objpas/namespaced/System.Tuples.pp

@@ -0,0 +1,3 @@
+unit System.Tuples;
+{$DEFINE FPC_DOTTEDUNITS}
+{$i tuples.pp}

+ 1 - 0
packages/rtl-objpas/namespaces.lst

@@ -9,6 +9,7 @@ src/inc/varutils.pp=namespaced/System.VarUtils.pp
 src/inc/convutils.pp=namespaced/System.ConvUtils.pp
 src/inc/convutils.pp=namespaced/System.ConvUtils.pp
 src/inc/dateutils.pp=namespaced/System.DateUtils.pp
 src/inc/dateutils.pp=namespaced/System.DateUtils.pp
 src/inc/nullable.pp=namespaced/System.Nullable.pp
 src/inc/nullable.pp=namespaced/System.Nullable.pp
+src/inc/tuples.pp=namespaced/System.Tuples.pp
 src/inc/rtti.pp=namespaced/System.Rtti.pp
 src/inc/rtti.pp=namespaced/System.Rtti.pp
 src/inc/widestrutils.pp=namespaced/System.WideStrUtils.pp
 src/inc/widestrutils.pp=namespaced/System.WideStrUtils.pp
 src/inc/syshelpers.pp=namespaced/System.Syshelpers.pp
 src/inc/syshelpers.pp=namespaced/System.Syshelpers.pp

+ 955 - 0
packages/rtl-objpas/src/inc/tuples.pp

@@ -0,0 +1,955 @@
+{$IFNDEF FPC_DOTTEDUNITS}
+unit tuples;
+{$ENDIF FPC_DOTTEDUNITS}
+
+{$mode objfpc}
+{$modeswitch advancedrecords}
+{$warn 5024 off}
+
+interface
+
+type
+
+  TPlaceHolder = record
+  end;
+
+  { TPair }
+
+  generic TPair<TFirst, TSecond> = record
+  public type
+    TSpecializedPair = specialize TPair<TFirst, TSecond>;
+  public
+    First: TFirst;
+    Second: TSecond;
+  private
+    class operator Initialize(var pair: TSpecializedPair);
+  public
+    constructor Create(constref AFirst: TFirst; constref ASecond: TSecond);
+
+    procedure Unpack(out AFirst: TFirst; out ASecond: TSecond);
+    procedure Unpack(const AFirst: TPlaceHolder; out ASecond: TSecond);
+    procedure Unpack(out AFirst: TFirst; const ASecond: TPlaceHolder);
+    procedure Unpack(const AFirst: TPlaceHolder; const ASecond: TPlaceHolder);
+  end;
+
+  { TTriple }
+
+  generic TTriple<TFirst, TSecond, TThird> = record
+  public type
+    TSpecializedTriple = specialize TTriple<TFirst, TSecond, TThird>;
+  public
+    First: TFirst;
+    Second: TSecond;
+    Third: TThird;
+  private
+    class operator Initialize(var triple: TSpecializedTriple);
+  public
+    constructor Create(constref AFirst: TFirst; constref ASecond: TSecond;
+                       constref AThird: TThird);
+
+    procedure Unpack(out AFirst: TFirst; out ASecond: TSecond;
+                     out AThird: TThird);
+    procedure Unpack(const AFirst: TPlaceHolder; out ASecond: TSecond;
+                     out AThird: TThird);
+    procedure Unpack(out AFirst: TFirst; const ASecond: TPlaceHolder;
+                     out AThird: TThird);
+    procedure Unpack(const AFirst: TPlaceHolder; const ASecond: TPlaceHolder;
+                     out AThird: TThird);
+    procedure Unpack(out AFirst: TFirst; out ASecond: TSecond;
+                     const AThird: TPlaceHolder);
+    procedure Unpack(const AFirst: TPlaceHolder; out ASecond: TSecond;
+                     const AThird: TPlaceHolder);
+    procedure Unpack(out AFirst: TFirst; const ASecond: TPlaceHolder;
+                     const AThird: TPlaceHolder);
+    procedure Unpack(const AFirst: TPlaceHolder; const ASecond: TPlaceHolder;
+                     const AThird: TPlaceHolder);
+  end;
+
+  { TQuadruple }
+
+  generic TQuadruple<TFirst, TSecond, TThird, TFourth> = record
+  public type
+    TSpecializedQuadruple = specialize TQuadruple<TFirst, TSecond, TThird, TFourth>;
+  public
+    First: TFirst;
+    Second: TSecond;
+    Third: TThird;
+    Fourth: TFourth;
+  private
+    class operator Initialize(var quadruple: TSpecializedQuadruple);
+  public
+    constructor Create(constref AFirst: TFirst; constref ASecond: TSecond;
+                       constref AThird: TThird; constref AFourth: TFourth);
+
+    procedure Unpack(out AFirst: TFirst; out ASecond: TSecond;
+                     out AThird: TThird; out AFourth: TFourth);
+    procedure Unpack(const AFirst: TPlaceHolder; out ASecond: TSecond;
+                     out AThird: TThird; out AFourth: TFourth);
+    procedure Unpack(out AFirst: TFirst; const ASecond: TPlaceHolder;
+                     out AThird: TThird; out AFourth: TFourth);
+    procedure Unpack(const AFirst: TPlaceHolder; const ASecond: TPlaceHolder;
+                     out AThird: TThird; out AFourth: TFourth);
+    procedure Unpack(out AFirst: TFirst; out ASecond: TSecond;
+                     const AThird: TPlaceHolder; out AFourth: TFourth);
+    procedure Unpack(const AFirst: TPlaceHolder; out ASecond: TSecond;
+                     const AThird: TPlaceHolder; out AFourth: TFourth);
+    procedure Unpack(out AFirst: TFirst; const ASecond: TPlaceHolder;
+                     const AThird: TPlaceHolder; out AFourth: TFourth);
+    procedure Unpack(const AFirst: TPlaceHolder; const ASecond: TPlaceHolder;
+                     const AThird: TPlaceHolder; out AFourth: TFourth);
+    procedure Unpack(out AFirst: TFirst; out ASecond: TSecond;
+                     out AThird: TThird; const AFourth: TPlaceHolder);
+    procedure Unpack(const AFirst: TPlaceHolder; out ASecond: TSecond;
+                     out AThird: TThird; const AFourth: TPlaceHolder);
+    procedure Unpack(out AFirst: TFirst; const ASecond: TPlaceHolder;
+                     out AThird: TThird; const AFourth: TPlaceHolder);
+    procedure Unpack(const AFirst: TPlaceHolder; const ASecond: TPlaceHolder;
+                     out AThird: TThird; const AFourth: TPlaceHolder);
+    procedure Unpack(out AFirst: TFirst; out ASecond: TSecond;
+                     const AThird: TPlaceHolder; const AFourth: TPlaceHolder);
+    procedure Unpack(const AFirst: TPlaceHolder; out ASecond: TSecond;
+                     const AThird: TPlaceHolder; const AFourth: TPlaceHolder);
+    procedure Unpack(out AFirst: TFirst; const ASecond: TPlaceHolder;
+                     const AThird: TPlaceHolder; const AFourth: TPlaceHolder);
+    procedure Unpack(const AFirst: TPlaceHolder; const ASecond: TPlaceHolder;
+                     const AThird: TPlaceHolder; const AFourth: TPlaceHolder);
+  end;
+
+  { TQuintuple }
+
+  generic TQuintuple<TFirst, TSecond, TThird, TFourth, TFifth> = record
+  public type
+    TSpecializedQuintuple = specialize TQuintuple<TFirst, TSecond, TThird,
+                                                  TFourth, TFifth>;
+  public
+    First: TFirst;
+    Second: TSecond;
+    Third: TThird;
+    Fourth: TFourth;
+    Fifth: TFifth;
+  private
+    class operator Initialize(var quintuple: TQuintuple);
+  public
+    constructor Create(constref AFirst: TFirst; constref ASecond: TSecond;
+                       constref AThird: TThird; constref AFourth: TFourth;
+                       constref AFifth: TFifth);
+
+    procedure Unpack(out AFirst: TFirst; out ASecond: TSecond;
+                     out AThird: TThird; out AFourth: TFourth;
+                     out AFifth: TFifth);
+    procedure Unpack(const AFirst: TPlaceHolder; out ASecond: TSecond;
+                     out AThird: TThird; out AFourth: TFourth;
+                     out AFifth: TFifth);
+    procedure Unpack(out AFirst: TFirst; const ASecond: TPlaceHolder;
+                     out AThird: TThird; out AFourth: TFourth;
+                     out AFifth: TFifth);
+    procedure Unpack(const AFirst: TPlaceHolder; const ASecond: TPlaceHolder;
+                     out AThird: TThird; out AFourth: TFourth;
+                     out AFifth: TFifth);
+    procedure Unpack(out AFirst: TFirst; out ASecond: TSecond;
+                     const AThird: TPlaceHolder; out AFourth: TFourth;
+                     out AFifth: TFifth);
+    procedure Unpack(const AFirst: TPlaceHolder; out ASecond: TSecond;
+                     const AThird: TPlaceHolder; out AFourth: TFourth;
+                     out AFifth: TFifth);
+    procedure Unpack(out AFirst: TFirst; const ASecond: TPlaceHolder;
+                     const AThird: TPlaceHolder; out AFourth: TFourth;
+                     out AFifth: TFifth);
+    procedure Unpack(const AFirst: TPlaceHolder; const ASecond: TPlaceHolder;
+                     const AThird: TPlaceHolder; out AFourth: TFourth;
+                     out AFifth: TFifth);
+    procedure Unpack(out AFirst: TFirst; out ASecond: TSecond;
+                     out AThird: TThird; const AFourth: TPlaceHolder;
+                     out AFifth: TFifth);
+    procedure Unpack(const AFirst: TPlaceHolder; out ASecond: TSecond;
+                     out AThird: TThird; const AFourth: TPlaceHolder;
+                     out AFifth: TFifth);
+    procedure Unpack(out AFirst: TFirst; const ASecond: TPlaceHolder;
+                     out AThird: TThird; const AFourth: TPlaceHolder;
+                     out AFifth: TFifth);
+    procedure Unpack(const AFirst: TPlaceHolder; const ASecond: TPlaceHolder;
+                     out AThird: TThird; const AFourth: TPlaceHolder;
+                     out AFifth: TFifth);
+    procedure Unpack(out AFirst: TFirst; out ASecond: TSecond;
+                     const AThird: TPlaceHolder; const AFourth: TPlaceHolder;
+                     out AFifth: TFifth);
+    procedure Unpack(const AFirst: TPlaceHolder; out ASecond: TSecond;
+                     const AThird: TPlaceHolder; const AFourth: TPlaceHolder;
+                     out AFifth: TFifth);
+    procedure Unpack(out AFirst: TFirst; const ASecond: TPlaceHolder;
+                     const AThird: TPlaceHolder; const AFourth: TPlaceHolder;
+                     out AFifth: TFifth);
+    procedure Unpack(const AFirst: TPlaceHolder; const ASecond: TPlaceHolder;
+                     const AThird: TPlaceHolder; const AFourth: TPlaceHolder;
+                     out AFifth: TFifth);
+    procedure Unpack(out AFirst: TFirst; out ASecond: TSecond;
+                     out AThird: TThird; out AFourth: TFourth;
+                     const AFifth: TPlaceHolder);
+    procedure Unpack(const AFirst: TPlaceHolder; out ASecond: TSecond;
+                     out AThird: TThird; out AFourth: TFourth;
+                     const AFifth: TPlaceHolder);
+    procedure Unpack(out AFirst: TFirst; const ASecond: TPlaceHolder;
+                     out AThird: TThird; out AFourth: TFourth;
+                     const AFifth: TPlaceHolder);
+    procedure Unpack(const AFirst: TPlaceHolder; const ASecond: TPlaceHolder;
+                     out AThird: TThird; out AFourth: TFourth;
+                     const AFifth: TPlaceHolder);
+    procedure Unpack(out AFirst: TFirst; out ASecond: TSecond;
+                     const AThird: TPlaceHolder; out AFourth: TFourth;
+                     const AFifth: TPlaceHolder);
+    procedure Unpack(const AFirst: TPlaceHolder; out ASecond: TSecond;
+                     const AThird: TPlaceHolder; out AFourth: TFourth;
+                     const AFifth: TPlaceHolder);
+    procedure Unpack(out AFirst: TFirst; const ASecond: TPlaceHolder;
+                     const AThird: TPlaceHolder; out AFourth: TFourth;
+                     const AFifth: TPlaceHolder);
+    procedure Unpack(const AFirst: TPlaceHolder; const ASecond: TPlaceHolder;
+                     const AThird: TPlaceHolder; out AFourth: TFourth;
+                     const AFifth: TPlaceHolder);
+    procedure Unpack(out AFirst: TFirst; out ASecond: TSecond;
+                     out AThird: TThird; const AFourth: TPlaceHolder;
+                     const AFifth: TPlaceHolder);
+    procedure Unpack(const AFirst: TPlaceHolder; out ASecond: TSecond;
+                     out AThird: TThird; const AFourth: TPlaceHolder;
+                     const AFifth: TPlaceHolder);
+    procedure Unpack(out AFirst: TFirst; const ASecond: TPlaceHolder;
+                     out AThird: TThird; const AFourth: TPlaceHolder;
+                     const AFifth: TPlaceHolder);
+    procedure Unpack(const AFirst: TPlaceHolder; const ASecond: TPlaceHolder;
+                     out AThird: TThird; const AFourth: TPlaceHolder;
+                     const AFifth: TPlaceHolder);
+    procedure Unpack(out AFirst: TFirst; out ASecond: TSecond;
+                     const AThird: TPlaceHolder; const AFourth: TPlaceHolder;
+                     const AFifth: TPlaceHolder);
+    procedure Unpack(const AFirst: TPlaceHolder; out ASecond: TSecond;
+                     const AThird: TPlaceHolder; const AFourth: TPlaceHolder;
+                     const AFifth: TPlaceHolder);
+    procedure Unpack(out AFirst: TFirst; const ASecond: TPlaceHolder;
+                     const AThird: TPlaceHolder; const AFourth: TPlaceHolder;
+                     const AFifth: TPlaceHolder);
+    procedure Unpack(const AFirst: TPlaceHolder; const ASecond: TPlaceHolder;
+                     const AThird: TPlaceHolder; const AFourth: TPlaceHolder;
+                     const AFifth: TPlaceHolder);
+  end;
+
+generic function Pair<TFirst, TSecond>(constref AFirst: TFirst; constref ASecond: TSecond):
+  specialize TPair<TFirst, TSecond>; inline;
+generic function Triple<TFirst, TSecond, TThird>(
+  constref AFirst: TFirst; constref ASecond: TSecond; constref AThird: TThird):
+  specialize TTriple<TFirst, TSecond, TThird>; inline;
+generic function Quadruple<TFirst, TSecond, TThird, TFourth>(
+  constref AFirst: TFirst; constref ASecond: TSecond; constref AThird: TThird;
+  constref AFourth: TFourth): specialize TQuadruple<TFirst, TSecond, TThird, TFourth>; inline;
+generic function Quintuple<TFirst, TSecond, TThird, TFourth, TFifth>(
+  constref AFirst: TFirst; constref ASecond: TSecond; constref AThird: TThird;
+  constref AFourth: TFourth; constref AFifth: TFifth):
+  specialize TQuintuple<TFirst, TSecond, TThird, TFourth, TFifth>; inline;
+
+
+generic function Tuple<TFirst, TSecond>(constref AFirst: TFirst; constref ASecond: TSecond):
+  specialize TPair<TFirst, TSecond>; overload; inline;
+generic function Tuple<TFirst, TSecond, TThird>(
+  constref AFirst: TFirst; constref ASecond: TSecond; constref AThird: TThird):
+  specialize TTriple<TFirst, TSecond, TThird>; overload; inline;
+generic function Tuple<TFirst, TSecond, TThird, TFourth>(
+  constref AFirst: TFirst; constref ASecond: TSecond; constref AThird: TThird;
+  constref AFourth: TFourth): specialize TQuadruple<TFirst, TSecond, TThird, TFourth>; overload; inline;
+generic function Tuple<TFirst, TSecond, TThird, TFourth, TFifth>(
+  constref AFirst: TFirst; constref ASecond: TSecond; constref AThird: TThird;
+  constref AFourth: TFourth; constref AFifth: TFifth):
+  specialize TQuintuple<TFirst, TSecond, TThird, TFourth, TFifth>; overload; inline;
+
+{$Push}
+{$WriteableConst Off}
+const
+  _: TPlaceHolder = ();
+{$Pop}
+
+implementation
+
+generic function Pair<TFirst, TSecond>(constref AFirst: TFirst; constref ASecond: TSecond):
+  specialize TPair<TFirst, TSecond>;
+begin
+  Result := specialize TPair<TFirst, TSecond>.Create(AFirst, ASecond);
+end;
+
+generic function Triple<TFirst, TSecond, TThird>(
+  constref AFirst: TFirst; constref ASecond: TSecond; constref AThird: TThird):
+  specialize TTriple<TFirst, TSecond, TThird>;
+begin
+  Result := specialize TTriple<TFirst, TSecond, TThird>.Create(AFirst, ASecond, AThird);
+end;
+
+generic function Quadruple<TFirst, TSecond, TThird, TFourth>(
+  constref AFirst: TFirst; constref ASecond: TSecond; constref AThird: TThird;
+  constref AFourth: TFourth): specialize TQuadruple<TFirst, TSecond, TThird, TFourth>;
+begin
+  Result := specialize TQuadruple<TFirst, TSecond, TThird, TFourth>.Create(
+    AFirst, ASecond, AThird, AFourth);
+end;
+
+generic function Quintuple<TFirst, TSecond, TThird, TFourth, TFifth>(
+  constref AFirst: TFirst; constref ASecond: TSecond; constref AThird: TThird;
+  constref AFourth: TFourth; constref AFifth: TFifth):
+  specialize TQuintuple<TFirst, TSecond, TThird, TFourth, TFifth>;
+begin
+  Result := specialize TQuintuple<TFirst, TSecond, TThird, TFourth, TFifth>.Create(
+    AFirst, ASecond, AThird, AFourth, AFifth);
+end;
+
+generic function Tuple<TFirst, TSecond>(constref AFirst: TFirst; constref ASecond: TSecond):
+  specialize TPair<TFirst, TSecond>;
+begin
+  Result := specialize TPair<TFirst, TSecond>.Create(AFirst, ASecond);
+end;
+
+generic function Tuple<TFirst, TSecond, TThird>(
+  constref AFirst: TFirst; constref ASecond: TSecond; constref AThird: TThird):
+  specialize TTriple<TFirst, TSecond, TThird>;
+begin
+  Result := specialize TTriple<TFirst, TSecond, TThird>.Create(AFirst, ASecond, AThird);
+end;
+
+generic function Tuple<TFirst, TSecond, TThird, TFourth>(
+  constref AFirst: TFirst; constref ASecond: TSecond; constref AThird: TThird;
+  constref AFourth: TFourth): specialize TQuadruple<TFirst, TSecond, TThird, TFourth>;
+begin
+  Result := specialize TQuadruple<TFirst, TSecond, TThird, TFourth>.Create(
+    AFirst, ASecond, AThird, AFourth);
+end;
+
+generic function Tuple<TFirst, TSecond, TThird, TFourth, TFifth>(
+  constref AFirst: TFirst; constref ASecond: TSecond; constref AThird: TThird;
+  constref AFourth: TFourth; constref AFifth: TFifth):
+  specialize TQuintuple<TFirst, TSecond, TThird, TFourth, TFifth>;
+begin
+  Result := specialize TQuintuple<TFirst, TSecond, TThird, TFourth, TFifth>.Create(
+    AFirst, ASecond, AThird, AFourth, AFifth);
+end;
+
+{ TQuintuple }
+
+class operator TQuintuple.Initialize(var quintuple: TQuintuple);
+begin
+  quintuple.First := Default(TFirst);
+  quintuple.Second := Default(TSecond);
+  quintuple.Third := Default(TThird);
+  quintuple.Fourth := Default(TFourth);
+  quintuple.Fifth := Default(TFifth);
+end;
+
+constructor TQuintuple.Create(constref AFirst: TFirst; constref
+  ASecond: TSecond; constref AThird: TThird; constref AFourth: TFourth;
+  constref AFifth: TFifth);
+begin
+  First := AFirst;
+  Second := ASecond;
+  Third := AThird;
+  Fourth := AFourth;
+  Fifth := AFifth;
+end;
+
+procedure TQuintuple.Unpack(out AFirst: TFirst; out ASecond: TSecond; out
+  AThird: TThird; out AFourth: TFourth; out AFifth: TFifth);
+begin
+  AFirst := First;
+  ASecond := Second;
+  AThird := Third;
+  AFourth := Fourth;
+  AFifth := Fifth;
+end;
+
+procedure TQuintuple.Unpack(const AFirst: TPlaceHolder; out ASecond: TSecond; out
+  AThird: TThird; out AFourth: TFourth; out AFifth: TFifth);
+begin
+  //AFirst := First;
+  ASecond := Second;
+  AThird := Third;
+  AFourth := Fourth;
+  AFifth := Fifth;
+end;
+
+procedure TQuintuple.Unpack(out AFirst: TFirst; const ASecond: TPlaceHolder; out
+  AThird: TThird; out AFourth: TFourth; out AFifth: TFifth);
+begin
+  AFirst := First;
+  //ASecond := Second;
+  AThird := Third;
+  AFourth := Fourth;
+  AFifth := Fifth;
+end;
+
+procedure TQuintuple.Unpack(const AFirst: TPlaceHolder; const ASecond: TPlaceHolder;
+  out AThird: TThird; out AFourth: TFourth; out AFifth: TFifth);
+begin
+  //AFirst := First;
+  //ASecond := Second;
+  AThird := Third;
+  AFourth := Fourth;
+  AFifth := Fifth;
+end;
+
+procedure TQuintuple.Unpack(out AFirst: TFirst; out ASecond: TSecond;
+  const AThird: TPlaceHolder; out AFourth: TFourth; out AFifth: TFifth);
+begin
+  AFirst := First;
+  ASecond := Second;
+  //AThird := Third;
+  AFourth := Fourth;
+  AFifth := Fifth;
+end;
+
+procedure TQuintuple.Unpack(const AFirst: TPlaceHolder; out ASecond: TSecond;
+  const AThird: TPlaceHolder; out AFourth: TFourth; out AFifth: TFifth);
+begin
+  //AFirst := First;
+  ASecond := Second;
+  //AThird := Third;
+  AFourth := Fourth;
+  AFifth := Fifth;
+end;
+
+procedure TQuintuple.Unpack(out AFirst: TFirst; const ASecond: TPlaceHolder;
+  const AThird: TPlaceHolder; out AFourth: TFourth; out AFifth: TFifth);
+begin
+  AFirst := First;
+  //ASecond := Second;
+  //AThird := Third;
+  AFourth := Fourth;
+  AFifth := Fifth;
+end;
+
+procedure TQuintuple.Unpack(const AFirst: TPlaceHolder; const ASecond: TPlaceHolder;
+  const AThird: TPlaceHolder; out AFourth: TFourth; out AFifth: TFifth);
+begin
+  //AFirst := First;
+  //ASecond := Second;
+  //AThird := Third;
+  AFourth := Fourth;
+  AFifth := Fifth;
+end;
+
+procedure TQuintuple.Unpack(out AFirst: TFirst; out ASecond: TSecond; out
+  AThird: TThird; const AFourth: TPlaceHolder; out AFifth: TFifth);
+begin
+  AFirst := First;
+  ASecond := Second;
+  AThird := Third;
+  //AFourth := Fourth;
+  AFifth := Fifth;
+end;
+
+procedure TQuintuple.Unpack(const AFirst: TPlaceHolder; out ASecond: TSecond; out
+  AThird: TThird; const AFourth: TPlaceHolder; out AFifth: TFifth);
+begin
+  //AFirst := First;
+  ASecond := Second;
+  AThird := Third;
+  //AFourth := Fourth;
+  AFifth := Fifth;
+end;
+
+procedure TQuintuple.Unpack(out AFirst: TFirst; const ASecond: TPlaceHolder; out
+  AThird: TThird; const AFourth: TPlaceHolder; out AFifth: TFifth);
+begin
+  AFirst := First;
+  //ASecond := Second;
+  AThird := Third;
+  //AFourth := Fourth;
+  AFifth := Fifth;
+end;
+
+procedure TQuintuple.Unpack(const AFirst: TPlaceHolder; const ASecond: TPlaceHolder;
+  out AThird: TThird; const AFourth: TPlaceHolder; out AFifth: TFifth);
+begin
+  //AFirst := First;
+  //ASecond := Second;
+  AThird := Third;
+  //AFourth := Fourth;
+  AFifth := Fifth;
+end;
+
+procedure TQuintuple.Unpack(out AFirst: TFirst; out ASecond: TSecond;
+  const AThird: TPlaceHolder; const AFourth: TPlaceHolder; out AFifth: TFifth);
+begin
+  AFirst := First;
+  ASecond := Second;
+  //AThird := Third;
+  //AFourth := Fourth;
+  AFifth := Fifth;
+end;
+
+procedure TQuintuple.Unpack(const AFirst: TPlaceHolder; out ASecond: TSecond;
+  const AThird: TPlaceHolder; const AFourth: TPlaceHolder; out AFifth: TFifth);
+begin
+  //AFirst := First;
+  ASecond := Second;
+  //AThird := Third;
+  //AFourth := Fourth;
+  AFifth := Fifth;
+end;
+
+procedure TQuintuple.Unpack(out AFirst: TFirst; const ASecond: TPlaceHolder;
+  const AThird: TPlaceHolder; const AFourth: TPlaceHolder; out AFifth: TFifth);
+begin
+  AFirst := First;
+  //ASecond := Second;
+  //AThird := Third;
+  //AFourth := Fourth;
+  AFifth := Fifth;
+end;
+
+procedure TQuintuple.Unpack(const AFirst: TPlaceHolder; const ASecond: TPlaceHolder;
+  const AThird: TPlaceHolder; const AFourth: TPlaceHolder; out AFifth: TFifth);
+begin
+  //AFirst := First;
+  //ASecond := Second;
+  //AThird := Third;
+  //AFourth := Fourth;
+  AFifth := Fifth;
+end;
+
+procedure TQuintuple.Unpack(out AFirst: TFirst; out ASecond: TSecond; out
+  AThird: TThird; out AFourth: TFourth; const AFifth: TPlaceHolder);
+begin
+  AFirst := First;
+  ASecond := Second;
+  AThird := Third;
+  AFourth := Fourth;
+  //AFifth := Fifth;
+end;
+
+procedure TQuintuple.Unpack(const AFirst: TPlaceHolder; out ASecond: TSecond; out
+  AThird: TThird; out AFourth: TFourth; const AFifth: TPlaceHolder);
+begin
+  //AFirst := First;
+  ASecond := Second;
+  AThird := Third;
+  AFourth := Fourth;
+  //AFifth := Fifth;
+end;
+
+procedure TQuintuple.Unpack(out AFirst: TFirst; const ASecond: TPlaceHolder; out
+  AThird: TThird; out AFourth: TFourth; const AFifth: TPlaceHolder);
+begin
+  AFirst := First;
+  //ASecond := Second;
+  AThird := Third;
+  AFourth := Fourth;
+  //AFifth := Fifth;
+end;
+
+procedure TQuintuple.Unpack(const AFirst: TPlaceHolder; const ASecond: TPlaceHolder;
+  out AThird: TThird; out AFourth: TFourth; const AFifth: TPlaceHolder);
+begin
+  //AFirst := First;
+  //ASecond := Second;
+  AThird := Third;
+  AFourth := Fourth;
+  //AFifth := Fifth;
+end;
+
+procedure TQuintuple.Unpack(out AFirst: TFirst; out ASecond: TSecond;
+  const AThird: TPlaceHolder; out AFourth: TFourth; const AFifth: TPlaceHolder);
+begin
+  AFirst := First;
+  ASecond := Second;
+  //AThird := Third;
+  AFourth := Fourth;
+  //AFifth := Fifth;
+end;
+
+procedure TQuintuple.Unpack(const AFirst: TPlaceHolder; out ASecond: TSecond;
+  const AThird: TPlaceHolder; out AFourth: TFourth; const AFifth: TPlaceHolder);
+begin
+  //AFirst := First;
+  ASecond := Second;
+  //AThird := Third;
+  AFourth := Fourth;
+  //AFifth := Fifth;
+end;
+
+procedure TQuintuple.Unpack(out AFirst: TFirst; const ASecond: TPlaceHolder;
+  const AThird: TPlaceHolder; out AFourth: TFourth; const AFifth: TPlaceHolder);
+begin
+  AFirst := First;
+  //ASecond := Second;
+  //AThird := Third;
+  AFourth := Fourth;
+  //AFifth := Fifth;
+end;
+
+procedure TQuintuple.Unpack(const AFirst: TPlaceHolder; const ASecond: TPlaceHolder;
+  const AThird: TPlaceHolder; out AFourth: TFourth; const AFifth: TPlaceHolder);
+begin
+  //AFirst := First;
+  //ASecond := Second;
+  //AThird := Third;
+  AFourth := Fourth;
+  //AFifth := Fifth;
+end;
+
+procedure TQuintuple.Unpack(out AFirst: TFirst; out ASecond: TSecond; out
+  AThird: TThird; const AFourth: TPlaceHolder; const AFifth: TPlaceHolder);
+begin
+  AFirst := First;
+  ASecond := Second;
+  AThird := Third;
+  //AFourth := Fourth;
+  //AFifth := Fifth;
+end;
+
+procedure TQuintuple.Unpack(const AFirst: TPlaceHolder; out ASecond: TSecond; out
+  AThird: TThird; const AFourth: TPlaceHolder; const AFifth: TPlaceHolder);
+begin
+  //AFirst := First;
+  ASecond := Second;
+  AThird := Third;
+  //AFourth := Fourth;
+  //AFifth := Fifth;
+end;
+
+procedure TQuintuple.Unpack(out AFirst: TFirst; const ASecond: TPlaceHolder; out
+  AThird: TThird; const AFourth: TPlaceHolder; const AFifth: TPlaceHolder);
+begin
+  AFirst := First;
+  //ASecond := Second;
+  AThird := Third;
+  //AFourth := Fourth;
+  //AFifth := Fifth;
+end;
+
+procedure TQuintuple.Unpack(const AFirst: TPlaceHolder; const ASecond: TPlaceHolder;
+  out AThird: TThird; const AFourth: TPlaceHolder; const AFifth: TPlaceHolder);
+begin
+  //AFirst := First;
+  //ASecond := Second;
+  AThird := Third;
+  //AFourth := Fourth;
+  //AFifth := Fifth;
+end;
+
+procedure TQuintuple.Unpack(out AFirst: TFirst; out ASecond: TSecond;
+  const AThird: TPlaceHolder; const AFourth: TPlaceHolder; const AFifth: TPlaceHolder);
+begin
+  AFirst := First;
+  ASecond := Second;
+  //AThird := Third;
+  //AFourth := Fourth;
+  //AFifth := Fifth;
+end;
+
+procedure TQuintuple.Unpack(const AFirst: TPlaceHolder; out ASecond: TSecond;
+  const AThird: TPlaceHolder; const AFourth: TPlaceHolder; const AFifth: TPlaceHolder);
+begin
+  //AFirst := First;
+  ASecond := Second;
+  //AThird := Third;
+  //AFourth := Fourth;
+  //AFifth := Fifth;
+end;
+
+procedure TQuintuple.Unpack(out AFirst: TFirst; const ASecond: TPlaceHolder;
+  const AThird: TPlaceHolder; const AFourth: TPlaceHolder; const AFifth: TPlaceHolder);
+begin
+  AFirst := First;
+  //ASecond := Second;
+  //AThird := Third;
+  //AFourth := Fourth;
+  //AFifth := Fifth;
+end;
+
+procedure TQuintuple.Unpack(const AFirst: TPlaceHolder; const ASecond: TPlaceHolder;
+  const AThird: TPlaceHolder; const AFourth: TPlaceHolder; const AFifth: TPlaceHolder);
+begin
+  //AFirst := First;
+  //ASecond := Second;
+  //AThird := Third;
+  //AFourth := Fourth;
+  //AFifth := Fifth;
+end;
+
+{ TQuadruple }
+
+class operator TQuadruple.Initialize(var quadruple: TSpecializedQuadruple);
+begin
+  quadruple.First := Default(TFirst);
+  quadruple.Second := Default(TSecond);
+  quadruple.Third := Default(TThird);
+  quadruple.Fourth := Default(TFourth);
+end;
+
+constructor TQuadruple.Create(constref AFirst: TFirst; constref
+  ASecond: TSecond; constref AThird: TThird; constref AFourth: TFourth);
+begin
+  First := AFirst;
+  Second := ASecond;
+  Third := AThird;
+  Fourth := AFourth;
+end;
+
+procedure TQuadruple.Unpack(out AFirst: TFirst; out ASecond: TSecond; out
+  AThird: TThird; out AFourth: TFourth);
+begin
+  AFirst := First;
+  ASecond := Second;
+  AThird := Third;
+  AFourth := Fourth;
+end;
+
+procedure TQuadruple.Unpack(const AFirst: TPlaceHolder; out ASecond: TSecond; out
+  AThird: TThird; out AFourth: TFourth);
+begin
+  //AFirst := First;
+  ASecond := Second;
+  AThird := Third;
+  AFourth := Fourth;
+end;
+
+procedure TQuadruple.Unpack(out AFirst: TFirst; const ASecond: TPlaceHolder; out
+  AThird: TThird; out AFourth: TFourth);
+begin
+  AFirst := First;
+  //ASecond := Second;
+  AThird := Third;
+  AFourth := Fourth;
+end;
+
+procedure TQuadruple.Unpack(const AFirst: TPlaceHolder; const ASecond: TPlaceHolder;
+  out AThird: TThird; out AFourth: TFourth);
+begin
+  //AFirst := First;
+  //ASecond := Second;
+  AThird := Third;
+  AFourth := Fourth;
+end;
+
+procedure TQuadruple.Unpack(out AFirst: TFirst; out ASecond: TSecond;
+  const AThird: TPlaceHolder; out AFourth: TFourth);
+begin
+  AFirst := First;
+  ASecond := Second;
+  //AThird := Third;
+  AFourth := Fourth;
+end;
+
+procedure TQuadruple.Unpack(const AFirst: TPlaceHolder; out ASecond: TSecond;
+  const AThird: TPlaceHolder; out AFourth: TFourth);
+begin
+  //AFirst := First;
+  ASecond := Second;
+  //AThird := Third;
+  AFourth := Fourth;
+end;
+
+procedure TQuadruple.Unpack(out AFirst: TFirst; const ASecond: TPlaceHolder;
+  const AThird: TPlaceHolder; out AFourth: TFourth);
+begin
+  AFirst := First;
+  //ASecond := Second;
+  //AThird := Third;
+  AFourth := Fourth;
+end;
+
+procedure TQuadruple.Unpack(const AFirst: TPlaceHolder; const ASecond: TPlaceHolder;
+  const AThird: TPlaceHolder; out AFourth: TFourth);
+begin
+  //AFirst := First;
+  //ASecond := Second;
+  //AThird := Third;
+  AFourth := Fourth;
+end;
+
+procedure TQuadruple.Unpack(out AFirst: TFirst; out ASecond: TSecond; out
+  AThird: TThird; const AFourth: TPlaceHolder);
+begin
+  AFirst := First;
+  ASecond := Second;
+  AThird := Third;
+  //AFourth := Fourth;
+end;
+
+procedure TQuadruple.Unpack(const AFirst: TPlaceHolder; out ASecond: TSecond; out
+  AThird: TThird; const AFourth: TPlaceHolder);
+begin
+  //AFirst := First;
+  ASecond := Second;
+  AThird := Third;
+  //AFourth := Fourth;
+end;
+
+procedure TQuadruple.Unpack(out AFirst: TFirst; const ASecond: TPlaceHolder; out
+  AThird: TThird; const AFourth: TPlaceHolder);
+begin
+  AFirst := First;
+  //ASecond := Second;
+  AThird := Third;
+  //AFourth := Fourth;
+end;
+
+procedure TQuadruple.Unpack(const AFirst: TPlaceHolder; const ASecond: TPlaceHolder;
+  out AThird: TThird; const AFourth: TPlaceHolder);
+begin
+  //AFirst := First;
+  //ASecond := Second;
+  AThird := Third;
+  //AFourth := Fourth;
+end;
+
+procedure TQuadruple.Unpack(out AFirst: TFirst; out ASecond: TSecond;
+  const AThird: TPlaceHolder; const AFourth: TPlaceHolder);
+begin
+  AFirst := First;
+  ASecond := Second;
+  //AThird := Third;
+  //AFourth := Fourth;
+end;
+
+procedure TQuadruple.Unpack(const AFirst: TPlaceHolder; out ASecond: TSecond;
+  const AThird: TPlaceHolder; const AFourth: TPlaceHolder);
+begin
+  //AFirst := First;
+  ASecond := Second;
+  //AThird := Third;
+  //AFourth := Fourth;
+end;
+
+procedure TQuadruple.Unpack(out AFirst: TFirst; const ASecond: TPlaceHolder;
+  const AThird: TPlaceHolder; const AFourth: TPlaceHolder);
+begin
+  AFirst := First;
+  //ASecond := Second;
+  //AThird := Third;
+  //AFourth := Fourth;
+end;
+
+procedure TQuadruple.Unpack(const AFirst: TPlaceHolder; const ASecond: TPlaceHolder;
+  const AThird: TPlaceHolder; const AFourth: TPlaceHolder);
+begin
+  //AFirst := First;
+  //ASecond := Second;
+  //AThird := Third;
+  //AFourth := Fourth;
+end;
+
+{ TTriple }
+
+class operator TTriple.Initialize(var triple: TSpecializedTriple);
+begin
+  triple.First := Default(TFirst);
+  triple.Second := Default(TSecond);
+  triple.Third := Default(TThird);
+end;
+
+constructor TTriple.Create(constref AFirst: TFirst; constref ASecond: TSecond;
+  constref AThird: TThird);
+begin
+  First := AFirst;
+  Second := ASecond;
+  Third := AThird;
+end;
+
+procedure TTriple.Unpack(out AFirst: TFirst; out ASecond: TSecond; out
+  AThird: TThird);
+begin
+  AFirst := First;
+  ASecond := Second;
+  AThird := Third;
+end;
+
+procedure TTriple.Unpack(const AFirst: TPlaceHolder; out ASecond: TSecond; out
+  AThird: TThird);
+begin
+  //AFirst := First;
+  ASecond := Second;
+  AThird := Third;
+end;
+
+procedure TTriple.Unpack(out AFirst: TFirst; const ASecond: TPlaceHolder; out
+  AThird: TThird);
+begin
+  AFirst := First;
+  //ASecond := Second;
+  AThird := Third;
+end;
+
+procedure TTriple.Unpack(const AFirst: TPlaceHolder; const ASecond: TPlaceHolder; out
+  AThird: TThird);
+begin
+  //AFirst := First;
+  //ASecond := Second;
+  AThird := Third;
+end;
+
+procedure TTriple.Unpack(out AFirst: TFirst; out ASecond: TSecond;
+  const AThird: TPlaceHolder);
+begin
+  AFirst := First;
+  ASecond := Second;
+  //AThird := Third;
+end;
+
+procedure TTriple.Unpack(const AFirst: TPlaceHolder; out ASecond: TSecond;
+  const AThird: TPlaceHolder);
+begin
+  //AFirst := First;
+  ASecond := Second;
+  //AThird := Third;
+end;
+
+procedure TTriple.Unpack(out AFirst: TFirst; const ASecond: TPlaceHolder;
+  const AThird: TPlaceHolder);
+begin
+  AFirst := First;
+  //ASecond := Second;
+  //AThird := Third;
+end;
+
+procedure TTriple.Unpack(const AFirst: TPlaceHolder; const ASecond: TPlaceHolder;
+  const AThird: TPlaceHolder);
+begin
+  //AFirst := First;
+  //ASecond := Second;
+  //AThird := Third;
+end;
+
+{ TPair }
+
+class operator TPair.Initialize(var pair: TSpecializedPair);
+begin
+  pair.First := Default(TFirst);
+  pair.Second := Default(TSecond);
+end;
+
+constructor TPair.Create(constref AFirst: TFirst; constref ASecond: TSecond);
+begin
+  First := AFirst;
+  Second := ASecond;
+end;
+
+procedure TPair.Unpack(out AFirst: TFirst; out ASecond: TSecond);
+begin
+  AFirst := First;
+  ASecond := Second;
+end;
+
+procedure TPair.Unpack(const AFirst: TPlaceHolder; out ASecond: TSecond);
+begin
+  //AFirst := First;
+  ASecond := Second;
+end;
+
+procedure TPair.Unpack(out AFirst: TFirst; const ASecond: TPlaceHolder);
+begin
+  AFirst := First;
+  //ASecond := Second;
+end;
+
+procedure TPair.Unpack(const AFirst: TPlaceHolder; const ASecond: TPlaceHolder);
+begin
+  //AFirst := First;
+  //ASecond := Second;
+end;
+
+end.
+

+ 411 - 0
tests/test/units/tuples/ttuple.pp

@@ -0,0 +1,411 @@
+program testtuples;
+
+{$mode objfpc}
+{$h+}
+
+uses tuples;
+
+Const
+  Val1  = 'Value 1';
+  Val2  = 42;
+  Val3  = Char('A');
+  Val4  = 3.14;
+  Val5  = True;
+
+Function TestPairAssign : String;
+
+Var
+  P : specialize TPair<String, Integer>;
+
+begin
+  P:=specialize Pair<String, Integer>(Val1, Val2);
+  if (P.First<>Val1) or (P.Second<>Val2) then
+    Exit('Pair construction failure');
+  P:=specialize Tuple<String, Integer>(Val1, Val2);
+  if (P.First<>Val1) or (P.Second<>Val2) then
+    Exit('Pair construction failure');
+  P:=specialize TPair<String, Integer>.Create(Val1, Val2);
+  if (P.First<>Val1) or (P.Second<>Val2) then
+    Exit('Pair construction failure');
+end;
+
+Function TestPairUnpack : String;
+
+Var
+  P : specialize TPair<String, Integer>;
+
+  A: String;
+  B: Integer;
+
+begin
+  P:=specialize Pair<String, Integer>(Val1, Val2);
+  A:='';
+  B:=0;
+  P.Unpack(A, _);
+  if A<>Val1 then
+    Exit('Pair unpack failure');
+  A:='';
+  P.Unpack(_, B);
+  if B<>Val2 then
+    Exit('Pair unpack failure');
+  B:=0;
+  P.unpack(A, B);
+  if (A<>Val1) or (B<>Val2) then
+    Exit('Pair unpack failure');
+end;
+
+Function TestTripleAssign : String;
+
+Var
+  P : specialize TTriple<String, Integer, Char>;
+
+begin
+  P:=specialize Triple<String, Integer, Char>(Val1, Val2, Val3);
+  if (P.First<>Val1) or (P.Second<>Val2) or (P.Third<>Val3) then
+    Exit('Triple construction failure');
+  P:=specialize Tuple<String, Integer, Char>(Val1, Val2, Val3);
+  if (P.First<>Val1) or (P.Second<>Val2) or (P.Third<>Val3)  then
+    Exit('Triple construction failure');
+  P:=specialize TTriple<String, Integer,Char>.Create(Val1, Val2, Val3);
+  if (P.First<>Val1) or (P.Second<>Val2) or (P.Third<>Val3)  then
+    Exit('Triple construction failure');
+end;
+
+Function TestTripleUnpack : String;
+
+Var
+  P : specialize TTriple<String, Integer, Char>;
+
+  A: String;
+  B: Integer;
+  C: Char;
+
+begin
+  P:=specialize Triple<String, Integer, Char>(Val1, Val2, Val3);
+  A:='';
+  B:=0;
+  C:=#00;
+  P.Unpack(A, _, _);
+  if A<>Val1 then
+    Exit('Triple unpack failure');
+  A:='';
+  P.Unpack(_, B, _);
+  if B<>Val2 then
+    Exit('Triple unpack failure');
+  B:=0;
+  P.unpack(_, _, C);
+  if C<>Val3 then
+    Exit('Triple unpack failure');
+  C:=#00;
+  P.unpack(A, B, _);
+  if (A<>Val1) or (B<>Val2) then
+    Exit('Triple unpack failure');
+  A:='';
+  B:=0;
+  P.unpack(A, _, C);
+  if (A<>Val1) or (C<>Val3) then
+    Exit('Triple unpack failure');
+  A:='';
+  C:=#00;
+  P.unpack(_, B, C);
+  if (B<>Val2) or (C<>Val3) then
+    Exit('Triple unpack failure');
+  B:=0;
+  C:=#00;
+  P.unpack(A, B, C);
+  if (A<>Val1) or (B<>Val2) or (C<>Val3)then
+    Exit('Triple unpack failure');
+end;
+
+Function TestQuadrupleAssign : String;
+
+Var
+  P : specialize TQuadruple<String, Integer, Char, Extended>;
+
+begin
+  P:=specialize Quadruple<String, Integer, Char, Extended>(Val1, Val2, Val3, Val4);
+  if (P.First<>Val1) or (P.Second<>Val2) or (P.Third<>Val3) or (P.Fourth<>Val4) then
+    Exit('Quadruple construction failure');
+  P:=specialize Tuple<String, Integer, Char, Extended>(Val1, Val2, Val3, Val4);
+  if (P.First<>Val1) or (P.Second<>Val2) or (P.Third<>Val3) or (P.Fourth<>Val4)  then
+    Exit('Quadruple construction failure');
+  P:=specialize TQuadruple<String, Integer,Char, Extended>.Create(Val1, Val2, Val3, Val4);
+  if (P.First<>Val1) or (P.Second<>Val2) or (P.Third<>Val3) or (P.Fourth<>Val4)  then
+    Exit('Quadruple construction failure');
+end;
+
+Function TestQuadrupleUnpack : String;
+
+Var
+  P : specialize TQuadruple<String, Integer, Char, Extended>;
+
+  A: String;
+  B: Integer;
+  C: Char;
+  D: Extended;
+
+begin
+  P:=specialize Quadruple<String, Integer, Char, Extended>(Val1, Val2, Val3, Val4);
+  A:='';
+  B:=0;
+  C:=#00;
+  D:=0.0;
+  P.Unpack(A, _, _, _);
+  if A<>Val1 then
+    Exit('Quadruple unpack failure');
+  A:='';
+  P.Unpack(_, B, _, _);
+  if B<>Val2 then
+    Exit('Quadruple unpack failure');
+  B:=0;
+  P.unpack(_, _, C, _);
+  if C<>Val3 then
+    Exit('Quadruple unpack failure');
+  C:=#00;
+  P.unpack(_, _, _, D);
+  if D<>Val4 then
+    Exit('Quadruple unpack failure');
+  D:=0.0;
+  P.unpack(A, B, _, _);
+  if (A<>Val1) or (B<>Val2) then
+    Exit('Quadruple unpack failure');
+  A:='';
+  B:=0;
+  P.unpack(A, _, C, _);
+  if (A<>Val1) or (C<>Val3) then
+    Exit('Quadruple unpack failure');
+  A:='';
+  C:=#00;
+  P.unpack(A, _, _, D);
+  if (A<>Val1) or (D<>Val4) then
+    Exit('Quadruple unpack failure');
+  A:='';
+  D:=0.0;
+  P.unpack(_, B, C, _);
+  if (B<>Val2) or (C<>Val3) then
+    Exit('Quadruple unpack failure');
+  B:=0;
+  C:=#00;
+  P.unpack(_, B, _, D);
+  if (B<>Val2) or (D<>Val4) then
+    Exit('Quadruple unpack failure');
+  B:=0;
+  D:=0.0;
+  P.unpack(_, _, C, D);
+  if (C<>Val3) or (D<>Val4) then
+    Exit('Quadruple unpack failure');
+  C:=#00;
+  D:=0.0;
+  P.unpack(A, B, C, _);
+  if (A<>Val1) or (B<>Val2) or (C<>Val3)then
+    Exit('Quadruple unpack failure');
+  A:='';
+  B:=0;
+  C:=#00;
+  P.unpack(A, B, _, D);
+  if (A<>Val1) or (B<>Val2) or (D<>Val4)then
+    Exit('Quadruple unpack failure');
+  A:='';
+  B:=0;
+  D:=0.0;
+  P.unpack(A, _, C, D);
+  if (A<>Val1) or (C<>Val3) or (D<>Val4)then
+    Exit('Quadruple unpack failure');
+  A:='';
+  C:=#00;
+  D:=0.0;
+  P.unpack(_, B, C, D);
+  if (B<>Val2) or (C<>Val3) or (D<>Val4)then
+    Exit('Quadruple unpack failure');
+  B:=0;
+  C:=#00;
+  D:=0.0;
+  P.unpack(A, B, C, D);
+  if (A<>Val1) or (B<>Val2) or (C<>Val3) or (D<>Val4) then
+    Exit('Quadruple unpack failure');
+end;
+
+Function TestQuintupleAssign : String;
+
+Var
+  P : specialize TQuintuple<String, Integer, Char, Extended, Boolean>;
+
+begin
+  P:=specialize Quintuple<String, Integer, Char, Extended, Boolean>(Val1, Val2, Val3, Val4, Val5);
+  if (P.First<>Val1) or (P.Second<>Val2) or (P.Third<>Val3) or (P.Fourth<>Val4) or (P.Fifth<>Val5) then
+    Exit('Quintuple construction failure');
+  P:=specialize Tuple<String, Integer, Char, Extended, Boolean>(Val1, Val2, Val3, Val4, Val5);
+  if (P.First<>Val1) or (P.Second<>Val2) or (P.Third<>Val3) or (P.Fourth<>Val4) or (P.Fifth<>Val5)  then
+    Exit('Quintuple construction failure');
+  P:=specialize TQuintuple<String, Integer,Char, Extended, Boolean>.Create(Val1, Val2, Val3, Val4, Val5);
+  if (P.First<>Val1) or (P.Second<>Val2) or (P.Third<>Val3) or (P.Fourth<>Val4) or (P.Fifth<>Val5)  then
+    Exit('Quintuple construction failure');
+end;
+
+Function TestQuintupleUnpack : String;
+
+Var
+  P : specialize TQuintuple<String, Integer, Char, Extended, Boolean>;
+
+  A: String;
+  B: Integer;
+  C: Char;
+  D: Extended;
+  E: Boolean;
+
+begin
+  P:=specialize Quintuple<String, Integer, Char, Extended, Boolean>(Val1, Val2, Val3, Val4, Val5);
+  A:='';
+  B:=0;
+  C:=#00;
+  D:=0.0;
+  E:=False;
+  P.Unpack(A, _, _, _, _);
+  if A<>Val1 then
+    Exit('Quintuple unpack failure');
+  A:='';
+  P.Unpack(_, B, _, _, _);
+  if B<>Val2 then
+    Exit('Quintuple unpack failure');
+  B:=0;
+  P.unpack(_, _, C, _, _);
+  if C<>Val3 then
+    Exit('Quintuple unpack failure');
+  C:=#00;
+  P.unpack(_, _, _, D, _);
+  if D<>Val4 then
+    Exit('Quintuple unpack failure');
+  D:=0.0;
+  P.unpack(_, _, _, _, E);
+  if E<>Val5 then
+    Exit('Quintuple unpack failure');
+  E:=False;
+  P.unpack(A, B, _, _, _);
+  if (A<>Val1) or (B<>Val2) then
+    Exit('Quintuple unpack failure');
+  A:='';
+  B:=0;
+  P.unpack(A, _, C, _, _);
+  if (A<>Val1) or (C<>Val3) then
+    Exit('Quintuple unpack failure');
+  A:='';
+  C:=#00;
+  P.unpack(A, _, _, D, _);
+  if (A<>Val1) or (D<>Val4) then
+    Exit('Quintuple unpack failure');
+  A:='';
+  D:=0.0;
+  P.unpack(A, _, _, _, E);
+  if (A<>Val1) or (E<>Val5) then
+    Exit('Quintuple unpack failure');
+  A:='';
+  E:=False;
+  P.unpack(_, B, C, _, _);
+  if (B<>Val2) or (C<>Val3) then
+    Exit('Quintuple unpack failure');
+  B:=0;
+  C:=#00;
+  P.unpack(_, B, _, D, _);
+  if (B<>Val2) or (D<>Val4) then
+    Exit('Quintuple unpack failure');
+  B:=0;
+  D:=0.0;
+  P.unpack(_, B, _, _, E);
+  if (B<>Val2) or (E<>Val5) then
+    Exit('Quintuple unpack failure');
+  B:=0;
+  E:=False;
+  P.unpack(_, _, C, D, _);
+  if (C<>Val3) or (D<>Val4) then
+    Exit('Quintuple unpack failure');
+  C:=#00;
+  D:=0.0;
+  P.unpack(_, _, C, _, E);
+  if (C<>Val3) or (E<>Val5) then
+    Exit('Quintuple unpack failure');
+  C:=#00;
+  E:=False;
+  P.unpack(_, _, _, D, E);
+  if (D<>Val4) or (E<>Val5) then
+    Exit('Quintuple unpack failure');
+  D:=0.0;
+  E:=False;
+  P.unpack(A, B, C, _, _);
+  if (A<>Val1) or (B<>Val2) or (C<>Val3)then
+    Exit('Quintuple unpack failure');
+  A:='';
+  B:=0;
+  C:=#00;
+  P.unpack(A, B, _, D, _);
+  if (A<>Val1) or (B<>Val2) or (D<>Val4)then
+    Exit('Quintuple unpack failure');
+  A:='';
+  B:=0;
+  D:=0.0;
+  P.unpack(A, B, _, _, E);
+  if (A<>Val1) or (B<>Val2) or (E<>Val5)then
+    Exit('Quintuple unpack failure');
+  A:='';
+  B:=0;
+  E:=False;
+  P.unpack(_, B, C, D, _);
+  if (B<>Val2) or (C<>Val3) or (D<>Val4)then
+    Exit('Quintuple unpack failure');
+  B:=0;
+  C:=#00;
+  D:=0.0;
+  P.unpack(_, B, C, _, E);
+  if (B<>Val2) or (C<>Val3) or (E<>Val5)then
+    Exit('Quintuple unpack failure');
+  B:=0;
+  C:=#00;
+  E:=False;
+  P.unpack(_, _, C, D, E);
+  if (C<>Val3) or (D<>Val4) or (E<>Val5)then
+    Exit('Quintuple unpack failure');
+  C:=#00;
+  D:=0.0;
+  E:=False;
+  P.unpack(A, B, C, D, _);
+  if (A<>Val1) or (B<>Val2) or (C<>Val3) or (D<>Val4) then
+    Exit('Quintuple unpack failure');
+  A:='';
+  B:=0;
+  C:=#00;
+  D:=0.0;
+  P.unpack(A, B, C, _, E);
+  if (A<>Val1) or (B<>Val2) or (C<>Val3) or (E<>Val5) then
+    Exit('Quintuple unpack failure');
+  A:='';
+  B:=0; 
+  C:=#00;
+  E:=False;
+  P.unpack(A, B, C, D, E);
+  if (A<>Val1) or (B<>Val2) or (C<>Val3) or (D<>Val4) or (E<>Val5) then
+    Exit('Quintuple unpack failure');
+end;
+
+Procedure DoTest(aTest,aResult : String);
+
+begin
+  if aResult<>'' then
+    begin
+    writeln(aTest,' failed : ',aResult);
+    Halt(1);
+    end
+  else
+    Writeln(aTest,' OK.');
+end;
+
+
+begin
+  DoTest('TestPairAssign',TestPairAssign);
+  DoTest('TestPairUnpack',TestPairUnpack); 
+  DoTest('TestTripleAssign',TestTripleAssign);
+  DoTest('TestTripleUnpack',TestTripleUnpack);
+  DoTest('TestQuadrupleAssign',TestQuadrupleAssign);
+  DoTest('TestQuadrupleUnpack',TestQuadrupleUnpack);
+  DoTest('TestQuintupleAssign',TestQuintupleAssign);
+  DoTest('TestQuintupleUnpack',TestQuintupleUnpack);
+end.
+