Ограничить параметр generi c для протоколов, ограниченных AnyObject - PullRequest
1 голос
/ 17 февраля 2020

Как я могу ограничить параметры универсального c типа протоколами, которые ограничены AnyObject?

Примечание. Я не хочу ограничить свой параметр AnyObject, я бы хотел бы разрешить протоколы в качестве параметров для моего обобщенного типа c, но только протоколы, которые сами ограничены AnyObject.

Пример:

struct Gen<P>
    where P: AnyObject     //  #1
{}

protocol CP: AnyObject {}
protocol SP {}

class C: CP {}
struct S: SP {}

let gc = Gen<CP>()         //  #2
let gs = Gen<SP>()         //  #3

Это дает ошибку как для №2, так и для # 3: 'Gen' requires that 'CP'/'SP' be a class type.

Если я удаляю строку # 1, то и # 2, и # 3 компилируются без ошибок.

Я хотел бы добиться, чтобы # 2 компилировался (потому что CP соответствует AnyObject), но # 3 не должен (потому что SP не соответствует AnyObject).

Есть ли способ сделать это?


В ответ на комментарий о том, почему я хочу это:

Я попытался реализовать WeakRef, чтобы у меня могли быть массивы (или другие коллекции), которые не сохраняют свои элементы , Я хотел, чтобы WeakRef разрешил протоколы в качестве своего параметра (а не только конкретные типы), чтобы я мог написать что-то вроде var observers: [MyObserverProtocol].

Единственный способ, который я нашел до сих пор (используя стирание типов), имеет недостаток, заключающийся в том, что теперь, если у меня есть протокол P и соответствующее значение типа T, то компилятор теперь позволяет мне объявлять переменную WeakRef<P> и оберните в нее экземпляр T, но он не будет работать во время выполнения (работает только с типами ref). Я хотел бы получить ошибку компиляции в этом случае. Поэтому я бы хотел, чтобы WeakRef разрешал только протоколы с ограниченным классом в качестве своего параметра.

struct WeakRef<T> {
    var value: T? { get { return (value_ as? T) }}
    weak var value_: AnyObject?
    init(value: T? = nil) { value_ = value as AnyObject }
}

Теперь WeakRef<ProtocolThatValueTypesCanConformTo> или даже WeakRef<ValueType> успешно компилируются, но, конечно, не будут работать во время выполнения, weakRef.value всегда будет nil.

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

Мне кажется, что это более общая проблема c, поэтому я не упомянул конкретный вариант использования c в исходном вопросе, но я могу ошибаться по этому поводу.

...