How can I constrain parameters of a generic type to protocols that are constrained to AnyObject?
Note I do not want to constrain my parameter to AnyObject, I'd like to allow protocols as parameters to my generic type, but only protocols that are themselves constrained to AnyObject.
Example:
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
This gives an error for both #2 and #3:
'Gen' requires that 'CP'/'SP' be a class type.
If I remove line #1, then both #2 and #3 compile with no error.
What I'd like to achieve is that #2 should compile (because CP conforms to AnyObject), but #3 should not (because SP does not conform to AnyObject).
Is there any way to do that?
In reply to a comment about why I'd want this:
I tried implementing a WeakRef, so I can have arrays (or other collections) that do not retain their elements. I wanted that WeakRef to allow protocols as its parameter (not only concrete types), so I can write something like var observers: [MyObserverProtocol]
.
The only way I found so far (using type erasure) has the drawback that now if I have a protocol P and a conforming value type T, then the compiler now allows me to declare a WeakRef<P>
variable, and wrap a T instance in it, but it won't work at runtime (only works with ref types). I'd like to get a compile error in this case. So I'd like WeakRef to only allow protocols that are class-constrained, as its parameter.
struct WeakRef<T> {
var value: T? { get { return (value_ as? T) }}
weak var value_: AnyObject?
init(value: T? = nil) { value_ = value as AnyObject }
}
Now WeakRef<ProtocolThatValueTypesCanConformTo>
or even WeakRef<ValueType>
happily compiles, but of course won't work at runtime, weakRef.value
will always be nil
.
I'd like to get a compile error if T is a value type, or if it's a protocol that value types are allowed to conform to. In these cases WeakRef doesn't really make sense, it only makes sense for ref types, and protocols that only ref types can conform to.
To me it feels like a more generic problem, that's why I didn't mention the specific use case in the original question, but I may be wrong about this.