Объединение универсальных шаблонов с различными ограничениями

У меня есть этот атомарный оптимистичный класс инициализатора:

type
  Atomic<T: IInterface> = class
    type TFactory = reference to function: T;
    class function Initialize(var storage: T; factory: TFactory): T;
  end;

class function Atomic<T>.Initialize(var storage: T; factory: TFactory): T;
var
  tmpIntf: T;
begin
  if not assigned(storage) then begin
    tmpIntf := factory();
    if InterlockedCompareExchangePointer(PPointer(@storage)^, PPointer(@tmpIntf)^, nil) = nil then
      PPointer(@tmpIntf)^ := nil;
  end;
  Result := storage;
end;

Теперь я хотел бы реализовать тот же шаблон для объектов.

type
  Atomic<T: class> = class
    type TFactory = reference to function: T;
    class function Initialize(var storage: T; factory: TFactory): T;
  end;

class function Atomic<T>.Initialize(var storage: T; factory: TFactory): T;
var
  tmpIntf: T;
begin
  if not assigned(storage) then begin
    tmpIntf := factory();
    if InterlockedCompareExchangePointer(PPointer(@storage)^, PPointer(@tmpIntf)^, nil) = nil then
      tmpIntf.Free;
  end;
  Result := storage;
end;

Я могу сделать это вдвоем за два. отдельные классы, но я бы действительно хотел поместить оба инициализатора под один и тот же зонтик. IOW, я бы в идеале использовал это как

var
  o: TObject;
  i: IInterface;

Atomic<TObject>.Initialize(o, CreateObject);
Atomic<IInterface>.Initialize(i, CreateInterface);

Я не могу найти для этого никакого хорошего решения. Единственная идея, которую я получил, - это объявить класс как Atomic (без ограничений), а затем каким-то образом (пока не знаю как) проверить RTTI T во время выполнения и действовать соответственно.

Мне эта идея не очень нравится, и я Я ищу лучший подход.

6
задан gabr 30 November 2011 в 12:23
поделиться