Take the example with storageValue
from the property delegate proposal. I think the pitched idea of storageValue
should be revisited as it‘s too magical and as @jrose pointed out in the other thread it shadows the property delegate type itself, which on the other hand makes it a perfect candidate for key-path lookup.
protocol Copyable: AnyObject {
func copy() -> Self
}
@propertyDelegate
@dynamicMemberLookup
struct CopyOnWrite<Value: Copyable> {
init(initialValue: Value) {
value = initialValue
}
private(set) var value: Value
var storageValue: Value {
mutating get {
if !isKnownUniquelyReferenced(&value) {
value = value.copy()
}
return value
}
set {
value = newValue
}
}
subscript<T>(dynamicMember keyPath: WritableKeyPath<Value, T>) -> T {
get { return storageValue[keyPath: keyPath] }
set { storageValue[keyPath: keyPath] = newValue }
}
}
class StorageManager {
func allocate<T>(_: T.Type) -> UnsafeMutablePointer<T> { ... }
}
@propertyDelegate
@dynamicMemberLookup
struct LongTermStorage<Value> {
let pointer: UnsafeMutablePointer<Value>
init(manager: StorageManager, initialValue: Value) {
pointer = manager.allocate(Value.self)
pointer.initialize(to: initialValue)
}
var value: Value {
get { return pointer.pointee }
set { pointer.pointee = newValue }
}
var storageValue: UnsafeMutablePointer<Value> {
return pointer
}
subscript<T>(
dynamicMember keyPath: WritableKeyPath<UnsafeMutablePointer<Value>, T>
) -> T {
get { return storageValue[keyPath: keyPath] }
set { storageValue[keyPath: keyPath] = newValue }
}
}