И ещё насчёт "STL". Обратил внимание на последние доклады Дня Оберона, в частности от Ильи Ермакова, где как-то вскользь косвенно представлены (однако, лишь мелькают на экране) некие "токены" и/или "тэги" (которые, к слову, вызывают недопонимание у участников конференции). Насколько я понимаю, в терминах СУБД, это некие домены как характеристики, определенные роли для типа (плюс возможность их сопоставления (равенство/сопоставимость типов), т.к. в runtime существуют переменные-singleton-ы соответствующего типа). Возможно существует и некая "STL" на таком базисе (м.б. даже без закулисной рефлексии), но на всякий случай. В таком стиле (плюс расширение "доменов" до их понимания как поля структур) мне когда-то попалась реализация "STL" для Freepascal/Delphi, когда там ещё не было дженериков -- библиотека AntiDOT (кажись, на форуме где-то уже была ссылка):
https://sourceforge.net/projects/adot/

Название AntiDOT понимается как "против DotNet", в смысле в целом против дизайна в Net фундаментального функционала (который тогда начал проникать в Delphi/Pascal).
Стиль тамошних "токенов" был (собственно, и есть) такой:
## Код:
```
General format of ADOT type construction:
    <DataType>.Create(<ContainerType> [,Field1Type [,Field2Type ...]])
  where
    <DataType> is any data-type class (TTString, TTByte, TTPointer, TTInteger, ...)
    <ContainerType> is any container class (TCVector, TCList, TCMap, TCHeap, ...)

  Examples:
    TTInteger.Create(TCSet)                         // set of integers
    TTWideString.Create(TCMap, [TTInteger]);        // map of string keys with integer values
    TTDouble.Create(TCVector, [TTDouble, TTString]) // vector of doubles with two additional fields
    TTString.Create(TCSet, [TTByte])                // set of strings with one additional field
    ...

  You don't have to remember all data-type classes. ADOT supports ALL Delphi
  built-in data types. Just write TT<type> where <type> is what you need
  (TTByte, TTString, TTInteger, TTDouble, ...)
...

// demonstrates creating of container with one field (TCVector, TCSList,
// TCDList, TCPriorityList, TCStack, TCDeque, ...)
procedure Demo1;
var
  n : TTInteger;
  m : TTDouble;
begin
  writeln;
  writeln('Vector of integers');
  n := TTInteger.create(TCVector);
  n.add([1,2,3,7,6,5]);
  n.Println(ffDefault, true);
  n.free;

  // Some containers MUST have two fields at least: TCMap, TCMultimap,
  // TCUnsortedMap. But we can add any number of additional fields to
  // any container!
  n := TTInteger.create(TCList, [TTDouble]);
  m := n.fields[1] as TTDouble;
  n.AddRecord([1, 0.999]);
  n.AddRecord([2, 1.785]);
  n.AddRecord([3, 3.1415926]);
  m[n.Add(4)] := 4.12;
  m[n.Add(5)] := 5.07;
  writeln;
  writeln('List with two fields');
  n.println;
  n.free;
end;

// demonstrates creating of container with two field (TCMap, TCMultimap,
// TCUnsortedmap)
// for mapping of doubles to strings
procedure Demo2;
var
  n : TTDouble;
  s : TTString;
begin
  writeln;
  writeln('Multimap(key: double; value: string)');
  n := TTDouble.create(TCMultimap, [TTString]);
  s := n.Fields[1] as TTString;

  // set some values with .Map property
  n.Map[3.14] := 'Pi';
  n.Map[2.72] := 'E';

  // another way to add data
  // now we have full checking of types in compile-time
  s[n.Add(1.618)] := 'Golden Ration';
  s[n.Add(1.618)] := 'Golden';

  // reassign
  n.Map[3.14] := 'pi';
  s[n.Find(2.72)] := 'e';

  n.Println;
  n.free;
end;

// demonstrates priority queue
procedure Demo5;
var
  n : TTInteger;
  f : TTString;
  h : TCHandle;
begin
  writeln;
  writeln('Priority queue');
  n := TTInteger.create(TCHeap, [TTString]);
  f := n.Fields[1] as TTString;
  f[n.Add(5)] := 'Five';
  f[n.Add(3)] := 'Three';
  f[n.Add(7)] := 'Seven';
  f[n.Add(0)] := 'Zero';
  f[n.Add(2)] := 'Two';
  f[n.Add(1)] := 'One';
  while n.Count>0 do
  begin
    h := n.FindMin;
    writeln(n[h], '->', f[h]);
    n.RemoveMinValue;
  end;
  n.Println;
  n.free;
end;

procedure Demo1;
var
  n: TTInteger;
  h: TCHandle;
  i,j: integer;
begin
  writeln;
  writeln('Vector of integers');
  n := TTInteger.create(TCVector);
  n.add([1,2,3,7,6,5]);

  // correct way to access items for any container
  h := n.First;
  for i:=0 to n.Count-1 do
  begin
    write(n[h], ' ');
    n.Next(h);
  end;
  writeln;

  // another way
  h := n.First;
  while h<>-1 do
  begin
    write(n[h], ' ');
    n.Next(h);
  end;
  writeln;

  // one more way
  h := n.First;
  while h<>-1 do
    write(n[n.MoveNext(h)], ' ');
  writeln;

  // accessing items by index (correct only for TCVector)
  for i := 0 to n.Count-1 do
    write(n[i], ' ');
  writeln;

  // accessing items by index (correct for all containers)
  for i := 0 to n.Count-1 do
    write(n[n.handles[i]], ' ');
  writeln;

  // find sum
  j := 0;
  for i := 0 to n.Count-1 do
    inc(j, n[n.handles[i]]);
  writeln('sum: ', j);

  n.free;
end;
```
