我在获取声明为的变量的大小时遇到问题 Any.Type
请参阅以下游乐场代码:
我有这个功能:
func genericSizeMe<T> (_ : T.Type) -> Int
{
return MemoryLayout<T>.size
}
Run Code Online (Sandbox Code Playgroud)
我是这样运行的:
let size1 = genericSizeMe(UInt32.self) // 4
let size2 = genericSizeMe(UInt16.self) // 2
var type1: UInt32.Type = UInt32.self
let size3 = genericSizeMe(type1) // 4
var type2: UInt16.Type = UInt16.self
let size4 = genericSizeMe(type2) // 2
var type3: Any.Type = UInt32.self
let size5 = genericSizeMe(type3) //ERROR
Run Code Online (Sandbox Code Playgroud)
这给出了错误:
/*
Playground execution failed:
error: MyPlayground.playground:14:13: error: cannot invoke 'genericSizeMe' with an argument list of type '(Any.Type)'
let size5 = genericSizeMe(type3)
^
MyPlayground.playground:14:13: note: expected an argument list of type '(T.Type)'
let size5 = genericSizeMe(type3)
^
*/
Run Code Online (Sandbox Code Playgroud)
如何(如果可能)解决这个问题?我想要实现的是拥有一个类型的数组,并获取每种类型的大小。像这样:
[UInt32.self, UInt8.self]
Run Code Online (Sandbox Code Playgroud)
并循环遍历数组并打印分配每种类型所需的字节大小。
如果更容易,我也可以接受在获取大小之前实际制作每种类型的实例。
您在使用通用函数时遇到的问题是,当通用占位符T是协议类型时P,T.Type则不是P.Type;它是P.Protocol。
因此,您不能将 an 传递Any.Type给T.Type参数(尽管Any从技术上讲它不是协议,但它是一种特殊的内置类型;在大多数情况下它具有协议的语义)。您需要传递代表具体类型的元类型。
因此,一种解决方案是为元类型构建一个类型擦除包装器,如检查 Swift 对象是否是给定元类型的实例所示:
struct AnyType {
let base: Any.Type
private let _memorySize: () -> Int
private let _memoryStride: () -> Int
private let _memoryAlignment: () -> Int
var memorySize: Int { return _memorySize() }
var memoryStride: Int { return _memoryStride() }
var memoryAlignment: Int { return _memoryAlignment() }
/// Creates a new AnyType wrapper from a given metatype.
/// The passed metatype's value **must** match its static value,
/// i.e `T.self == base` must be `true`.
init<T>(_ base: T.Type) {
precondition(T.self == base, """
The static value \(T.self) and dynamic value \(base) of the \
passed metatype do not match
"""
)
self.base = T.self
self._memorySize = { MemoryLayout<T>.size }
self._memoryStride = { MemoryLayout<T>.stride }
self._memoryAlignment = { MemoryLayout<T>.alignment }
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以像这样使用它:
struct S {
var i: Int
var b: Bool
}
let types = [AnyType(UInt32.self), AnyType(UInt8.self), AnyType(S.self)]
for type in types {
print("Size of \(type.base): \(type.memorySize)")
print("Stride of \(type.base): \(type.memoryStride)")
print("Alignment of \(type.base): \(type.memoryAlignment)")
print()
}
// Size of UInt32: 4
// Stride of UInt32: 4
// Alignment of UInt32: 4
//
// Size of UInt8: 1
// Stride of UInt8: 1
// Alignment of UInt8: 1
//
// Size of S: 9
// Stride of S: 16
// Alignment of S: 8
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
834 次 |
| 最近记录: |