在 Nim 中工作时,我对模板的直觉是,在编译时,它们只是简单地扩展到代码中(通过适当的替换)。但是下面的代码:
type
New_Type = ref object of RootObj
template Template_Procedure(T: untyped, vProc: bool = true) =
proc ProcedureA(self:var T, vInt: var int): int
when vProc == true:
proc ProcedureA(self:var T, vInt: var int): int =
var tReturn = vInt * vInt
return tReturn
proc ProcedureB(self: var T, vInt: var int): int =
var tI = ProcedureA(self, vInt)
return 2 * tI
Template_Procedure(New_Type, vProc = false)
proc ProcedureA(self:var New_Type, vInt: var int): int =
var tReturn = vInt * vInt * vInt
return tReturn
var tNew = new(New_Type)
var tInt = 5
echo $ProcedureB(tNew, tInt)
给出错误:
test3.nim(9, 10) Error: implementation of 'test3.ProcedureA(self`gensym0: var New_Type, vInt`gensym0: var int)' expected
然而如果我打电话
Template_Procedure(New_Type, vProc = true)
那么就没有错误了。
相反,如果我手动将模板的文本替换为调用它的位置,则会发生相反的情况。即,如果我将 vProc 替换为 false,则代码将编译并收到错误
Error: redefinition of 'ProcedureA'; previous declaration
如果我用 true 代替 vProc。
有人可以向我解释我对模板的直觉在哪里不正确吗?(或给我适当的参考资料)
另外,有没有一种方法可以编写在编译时简单扩展的代码?
具体来说,我希望能够调用 Template_Procedure(X, vProc = false),其中 X 是一种类型,然后,对于适当的类型 X,手动编写特定的
ProcedureA(self: var X, vInt var int): int
程序。对于其他X,只需调用Template_Procedure(X),而不必手动定义ProcedureA。
前向声明永远不会得到实现,因为模板是卫生的。尽管它们看起来都有相同的名称,
ProcedureA
因为您位于模板空间内,但它们的名称并不相同。您可能应该标记模板{.dirty.}
或{.inject.}
在过程中使用来注入符号名称。对于下面的问题我不知道你的意思,模板只是扩展。