typedesc[T]
在一些上下文中,Nim 把类型名当作常规的值处理。这些值只存在于编译阶段,由于所有的值都必须有类型, 就用 typedesc 来表示它们的这种特殊类型。
typedesc 作为泛型类型。例如,标识符 int 的类型是 typedesc[int] 。 和普通的泛型一样,当省略泛型参数时,typedesc 就表示所有的类型类。 作为一种语法上的便利,我们也可以使用 typedesc 作为修饰语。
具有 typedesc 参数的过程,被当成是隐式泛型的。 它们按提供类型的每个特定组合来实例化,并在过程主体中,每个参数名称将指代为绑定的具体类型。
proc new(T: typedesc): ref T =
echo "allocating ", T.name
new(result)
var n = Node.new
var tree = new(BinaryTree[int])
当出现多个类型参数时,它们将自由绑定到不同的类型。可以使用明确的泛型参数,来强制执行一次性绑定。
proc acceptOnlyTypePairs[T, U](A, B: typedesc[T]; C, D: typedesc[U])
一旦绑定,类型参数就可以出现在过程签名的其它部分:
template declareVariableWithType(T: typedesc, value: T) =
var x: T = value
declareVariableWithType int, 42
通过限制与类型参数相匹配的类型集,可以进一步影响重载解析。在实践中,通过模板将属性附加到类型上。该约束可以是一个具体的类型或一个类型类。
template maxval(T: typedesc[int]): int = high(int)
template maxval(T: typedesc[float]): float = Inf
var i = int.maxval
var f = float.maxval
when false:
var s = string.maxval # error, maxval is not implemented for string
template isNumber(t: typedesc[object]): string = "不这么看。"
template isNumber(t: typedesc[SomeInteger]): string = "是的!"
template isNumber(t: typedesc[SomeFloat]): string = "有可能,也可能是 NaN。"
echo "int 是数字吗? ", isNumber(int)
echo "float 是数字吗? ", isNumber(float)
echo "RootObj 是数字吗? ", isNumber(RootObj)
给宏传入 typedesc 与传入其它参数几乎是一样的,区别仅在于宏一般不会被实例化。类型表达式简单地作为 NimNode 传给宏,就像其它任何东西一样。
import std/macros
macro forwardType(arg: typedesc): typedesc =
# `arg` 的类型是 `NimNode`
let tmp: NimNode = arg
result = tmp
var tmp: forwardType(int)
当前内容版权归 vectorworkshopbaoerjie 或其关联方所有,如需对内容或内容相关联开源项目进行关注与资助,请访问 vectorworkshopbaoerjie .