已归档:使用 @inlinable
。
一个对等宏,用于将泛型 结构体或类 扩展为专门的类型。当您公开带有大量泛型的公共 API,并且知道一些特定的、经常使用的特化时,这有助于 Swift 更好地特化/优化您的代码。 在某种意义上,这个宏使 Swift 中的泛型更像 C++ 模板。
enum Namespace {
@WithSpecializedGenerics("public typealias Hola<S> = Hello<Int, S>;public typealias Hej<S> = Hello<String, S>")
final class Hello<T, S>: Identifiable where T: Hashable, S.ID == T, S: Identifiable {
let id: T
let children: Hello<T, S>
let name = #ReplaceWhenSpecializing("Hello!", "\"¡Hola!\"")
func greeting(with word: Hello<T, S>) -> Hello<T, S> {
let _: Hello<T, S> = Hello(id: word.id, children: word.children)
return Hello<T, S>(id: word.id, children: word.children)
}
init(id: T, children: Hello<T, S>) {
self.id = id
self.children = children.children
}
}
}
将被扩展为
enum Namespace {
final class Hello<T, S>: Identifiable where T: Hashable, S.ID == T, S: Identifiable {
let id: T
let children: Hello<T, S>
let name = "Hello!"
func greeting(with word: Hello<T, S>) -> Hello<T, S> {
let _: Hello<T, S> = Hello(id: word.id, children: word.children)
return Hello<T, S>(id: word.id, children: word.children)
}
init(id: T, children: Hello<T, S>) {
self.id = id
self.children = children.children
}
}
final class Hola<S>: Identifiable where S.ID == Int, S: Identifiable {
let id: T
let children: Hola<S>
let name = "¡Hola!"
func greeting(with word: Hola<S>) -> Hola<S> {
let _: Hola<S> = Hola(id: word.id, children: word.children)
return Hola<S>(id: word.id, children: word.children)
}
init(id: T, children: Hola<S>) {
self.id = id
self.children = children.children
}
public typealias T = Int
}
final class Hej<S>: Identifiable where S.ID == String, S: Identifiable {
let id: T
let children: Hej<S>
let name = "¡Hola!"
func greeting(with word: Hej<S>) -> Hej<S> {
let _: Hej<S> = Hej(id: word.id, children: word.children)
return Hej<S>(id: word.id, children: word.children)
}
init(id: T, children: Hej<S>) {
self.id = id
self.children = children.children
}
public typealias T = String
}
}
由于对等宏无法在全局范围内引入新名称,因此需要 enum Namespace
。
宏 @WithSpecializedGenerics("typealias ...")
接受一个 typealias
语法列表,并容许 final
修饰符。 内部的字符串也 **使用 SwiftSyntax
包进行解析**。 这意味着只要您提供一个可解析的类型别名列表,它就可以工作。 该宏为您执行 6 项操作
where
子句中的冗余泛型要求。"typealias ... where ..."
中的泛型要求复制到原始 where
子句。该软件包还提供了一个 #ReplaceWhenSpecialing(#OldExpr#, "NewExpr")
宏,它在特化时将所有出现的 #OldExpr#
替换为 NewExpr
。 #OldExpr#
必须是有效的表达式,而 NewExpr
可以是任何字符串。 当您有一些特定的实现时,这会派上用场。
对于 四叉树数据结构(第 48 行) 中的用例,与直接使用类型别名语法相比,此宏可以将数据结构的构建时间加快约 16%。 诸如遍历树节点之类的用例可以从中获得更多益处。
即使启用了 -cross-module-optimization
标志,我也观察到使用这种方法可以显着提高性能。(在此处的测试用例中,从 0.17 秒到 0.04 秒)
注意
对于泛型函数,请尝试 @_specialize
属性。
注意
目前,此宏不特别注意 AnotherNamespace.StructOrClassWithSameName
,因此在遇到这种情况时可能会引入不需要的代码。
注意
如果您在同一个文件中向原始泛型类型添加扩展,并且遇到错误 Circular reference
,则将扩展移动到另一个文件可以解决此问题。 这可能类似于此处讨论的问题:swiftlang/swift#66450 。