Now I have following property wrapper using dynamic member lookup.
@propertyWrapper
@dynamicMemberLookup
private struct AddSubscript<T, S> {
var wrappedValue: T
init(wrappedValue: T, type: S.Type) {
self.wrappedValue = wrappedValue
}
subscript(to type: HashableMetatype<S>) -> Bool {
get {
return true
}
set {
//some process
}
}
subscript<U>(dynamicMember keyPath: WritableKeyPath<T, U>) -> U{
get {
return wrappedValue[keyPath: keyPath]
}
set {
wrappedValue[keyPath: keyPath] = newValue
}
}
}
enum HashableMetatype<T>: Hashable {
case type(T.Type)
static func == (lhs: HashableMetatype<T>, rhs: HashableMetatype<T>) -> Bool {
return true
}
func hash(into hasher: inout Hasher) {}
}
HashableMetatype
allows me to use the metatype as the key of subscript
, but it is not main topic.
I want this property wrapper to work as if it add subscripts, because I thought dynamic member lookup can bring all of added subscripts.
struct Test{
@AddSubscript(type: Double.self)
@AddSubscript(type: String.self)
@AddSubscript(type: Bool.self)
@AddSubscript(type: Int.self)
private var value = true
func test(){
print(_value[to: .type(Double.self)]) //it should work and it works.
print(_value[to: .type(String.self)]) //it should work and it works.
//Cannot convert value of type 'Bool.Type' to expected argument type 'Double.Type'
print(_value[to: .type(Bool.self)]) //it should work but it doesn't works!
//Cannot convert value of type 'Int.Type' to expected argument type 'Double.Type'
print(_value[to: .type(Int.self)]) //it should work but it doesn't works!
let keyPath: KeyPath<AddSubscript<Bool, Int>, Bool> = \.[to: .type(Int.self)]
let keyPath2: KeyPath<AddSubscript<AddSubscript<Bool, Int>, Bool>, Bool> = \.[to: .type(Int.self)]
let keyPath3: KeyPath<AddSubscript<AddSubscript<Bool, Int>, Bool>, Bool> = \.[to: .type(Bool.self)]
let keyPath4: KeyPath<AddSubscript<AddSubscript<AddSubscript<Bool, Int>, Bool>, String>, Bool> = \.[to: .type(String.self)]
let keyPath5: KeyPath<AddSubscript<AddSubscript<AddSubscript<Bool, Int>, Bool>, String>, Bool> = \.[to: .type(Bool.self)]
//Only this causes error!
let keyPath6: KeyPath<AddSubscript<AddSubscript<AddSubscript<Bool, Int>, Bool>, String>, Bool> = \.[to: .type(Int.self)]
}
}
I thought dynamic member lookup can use all keyPaths that KeyPath<T, U>
can represent.
Because AddSubscript<AddSubscript<Bool, Int>, Bool>
has KeyPath let keyPath2 = \.[to: .type(Int.self)]
, it is natural that let keyPath6 = \.[to: .type(Int.self)]
works.
My question is, what is the expected behavior when wrapped value of @dynamicMemberLookup struct Wrapper<T>
has also attribute @dynamicMemberLookup
. Is the error is expected? Or, is my understanding wrong...?