• typedesc[T]

    typedesc[T]

    在许多情况下,Nim允许您将类型的名称视为常规值。 这些值仅在编译阶段存在,但由于所有值必须具有类型,因此 typedesc 被视为其特殊类型。

    typedesc 就像一个通用类型。例如,符号 int 的类型是 typedesc [int] 。 就像常规泛型类型一样,当泛型参数被省略时,typedesc表示所有类型的类型类。 作为一种语法方便,您还可以使用typedesc作为修饰符。

    具有 typedesc 参数的过程被认为是隐式通用的。 它们将针对提供的类型的每个唯一组合进行实例化,并且在proc的主体内,每个参数的名称将引用绑定的具体类型:

    1. proc new(T: typedesc): ref T =
    2. echo "allocating ", T.name
    3. new(result)
    4.  
    5. var n = Node.new
    6. var tree = new(BinaryTree[int])

    当存在多种类型的参数时,它们将自由地绑定到不同类型。 要强制绑定一次行为,可以使用显式通用参数:

    1. proc acceptOnlyTypePairs[T, U](A, B: typedesc[T]; C, D: typedesc[U])

    绑定后,类型参数可以出现在proc签名的其余部分中:

    1. template declareVariableWithType(T: typedesc, value: T) =
    2. var x: T = value
    3.  
    4. declareVariableWithType int, 42

    通过约束与类型参数匹配的类型集,可以进一步影响重载解析。 这在实践中通过模板将属性附加到类型。 约束可以是具体类型或类型类。

    1. template maxval(T: typedesc[int]): int = high(int)
    2. template maxval(T: typedesc[float]): float = Inf
    3.  
    4. var i = int.maxval
    5. var f = float.maxval
    6. when false:
    7. var s = string.maxval # 错误,没有为字符串实现maxval
    8.  
    9. template isNumber(t: typedesc[object]): string = "Don't think so."
    10. template isNumber(t: typedesc[SomeInteger]): string = "Yes!"
    11. template isNumber(t: typedesc[SomeFloat]): string = "Maybe, could be NaN."
    12.  
    13. echo "is int a number? ", isNumber(int)
    14. echo "is float a number? ", isNumber(float)
    15. echo "is RootObj a number? ", isNumber(RootObj)

    传递 typedesc 几乎完全相同,只是因为宏没有一般地实例化。 类型表达式简单地作为 NimNode 传递给宏,就像其他所有东西一样。

    1. import macros
    2.  
    3. macro forwardType(arg: typedesc): typedesc =
    4. # ``arg`` 是 ``NimNode`` 类型
    5. let tmp: NimNode = arg
    6. result = tmp
    7.  
    8. var tmp: forwardType(int)