Есть библиотека для работы с динамическими структурами данных. Ее очень упрощенная часть представлена ниже (компилятор - FPC 2.0.0 под Win32):
{$mode ObjFpc}
Type
T = Integer;
ptitem = ^titem;
titem = Object
info: T;
next, prev: ptitem;
Constructor init(x: T; nxt, prv: ptitem);
Destructor done;
End;
Type
TList = Object
Private
first, last: ptitem;
Function isEmpty: Boolean;
Public
Constructor Create;
Destructor Destroy; Virtual;
Procedure append(x: T);
Procedure insert(x: T);
Procedure Print;
End;
Operator + (Const L: TList; it: T) R: TList;
Begin
L.append(it);
result := L;
End;
Operator + (it: T; Const L: TList) R: TList;
Begin
L.insert(it);
result := L;
End;
Constructor titem.init(x: T; nxt, prv: ptitem);
Begin
info := x;
next := nxt; prev := prv;
End;
Destructor titem.done;
Begin End;
(* tlist *)
Constructor TList.Create;
Begin
first := nil; last := nil;
End;
Destructor TList.Destroy;
Begin
// ...
End;
Function TList.isEmpty: Boolean;
Begin
isEmpty := (first = nil);
End;
{
insert new item to the start of list
}
Procedure TList.insert(x: T);
Var p: ptitem;
Begin
new(p, init(x, first, nil));
If p <> nil Then Begin
If isEmpty Then last := p
Else first^.prev := p;
first := p;
End;
End;
{
append new item to the end of list
}
Procedure TList.append(x: T);
Var p: ptitem;
Begin
new(p, init(x, nil, last));
If p <> nil Then Begin
If isEmpty Then first := p
Else last^.next := p;
last := p;
End;
End;
Procedure TList.Print;
Var pt: ptitem;
Begin
Write('<');
pt := first;
While pt <> nil Do Begin
write(pt^.info, ' ');
pt := pt^.next
End;
WriteLn('>')
End;
var
list_int: TList;
i: integer;
begin
list_int.create;
// Здесь работаем по-старинке:
list_int.insert(10); // Добавляем элемент в начало списка
list_int.insert(20); // ...
list_int.append(30); // Добавляем элемент в конец списка
list_int.append(40); // ...
list_int.print;
// А здесь - используем возможности современного компилятора -
// перегрузку операций
for i := 1 to 8 do
list_int := (15 * i) + list_int + (10 * i);
list_int.print;
list_int.destroy;
end.
Все компилируется и работает. Меня интересует такой вопрос: насколько удобно будет пользователю библиотеки перейти от привычной формы записи (в виде процедур) к записи вида:
ListObj := 12 + 17 + ListObj + 24 + 32 + 78; { <--- Это, кстати, тоже работает... }, и стоит ли вообще предоставлять ему такую возможность и заморачиваться с перегрузкой операций?
Еще кое-что... Тип T не всегда будет Integer, вполне возможно, что там будет указатель на какой-то объект. Вопрос, собственно, в том, распространяются ли на operator overloading правила наследования, то есть, смогу ли я передавать левым/правым операндом, например, указатели на объекты, находящиеся на разном уровне иерархии наследования, или только указатель на базовый класс?