gpt4 book ai didi

templates - dlang 模板和模板化类、结构和函数之间的区别

转载 作者:行者123 更新时间:2023-12-03 15:06:29 26 4
gpt4 key购买 nike

我在理解 D 中的模板时遇到了一些麻烦。

我了解 struct Foo(T) { }或类或函数的等价物,但 template Bar(T) { } 是什么? ?它与类、结构或函数模板有何不同,我什么时候使用?

最佳答案

嗯,从技术上讲,

struct S(T)
{
...
}

相当于
template S(T)
{
struct S
{
...
}
}


auto foo(T)(T t)
{
...
}

相当于
template foo(T)
{
auto foo(T t)
{
...
}
}

只是提供了较短的语法以使常见用例的内容更简洁。 template创建代码生成模板。在使用参数实例化模板之前,该模板中的任何内容都不作为真实代码存在,并且生成的代码取决于模板参数。因此,模板的语义分析直到它被实例化才完成。

将模板作为其声明的一部分而不是显式声明模板来包装它们的结构、类和函数所发生的部分情况就是所谓的同名模板。使用模板时,其中包含与模板同名的符号的任何模板都将替换为该符号。例如
template isInt(T)
{
enum isInt = is(T == int);
}

然后可以在表达式中使用,例如
auto foo = isInt!int;

和枚举的值 isInt.isInt用在表达式中代替模板。这种技术在模板约束的帮助模板中大量使用。例如 isInputRange
auto foo(R)(R range)
if(isInputRange!R)
{...}

isInputRange 被定义为同名模板,结果为 true如果给定类型是输入范围和 false除此以外。在某种程度上,它有点像拥有一个对类型进行操作的函数,尽管它也可以对值进行操作,并且结果不必是 bool .例如
template count(Args...)
{
enum count = Args.length;
}

或者
template ArrayOf(T)
{
alias ArrayOf = T[];
}

如果同名模板没有任何其他成员,则它们不是用户定义的类型或函数,还有一种快捷语法。例如
enum count(Args...) = Args.length;
alias ArrayOf(T) = T[];

正如我所说,同名模板有点像拥有一个对类型进行操作的函数,这就是需要对类型进行复杂操作时使用的模板。例如,使用 ArrayOf带有 std.meta.staticMap 的模板,你可以做类似的事情
alias Arrays = staticMap!(ArrayOf, int, float, byte, bool);
static assert(is(Arrays == AliasSeq!(int[], float[], byte[], bool[])));

这在模板约束(或模板约束中使用的其他同名模板)中非常有用,或者它可以与静态 foreach 之类的东西一起使用以更明确地生成代码。例如如果我想用所有字符串类型测试一些代码,我可以写类似
alias Arrays(T) = AliasSeq!(T[],
const(T)[],
const(T[]),
immutable(T)[],
immutable(T[]));

unittest
{
import std.conv : to;
static foreach(S; AliasSeq(Arrays!char, Arrays!wchar, Arrays!dchar))
{{
auto s = to!S("foo");
...
}}
}

这些技术通常在元编程中大量使用。除了类型之外,它们还可以用于值,但将 CTFE 用于值通常比将它们放在 AliasSeq 中更有效。并在其上使用各种同名模板。例如,几年前,Phobos 曾经拥有同名模板 Format它用于在编译时生成字符串,类似于 std.format.format在运行时执行此操作,但一旦 CTFE 改进到 format可以在编译时使用,使用 Format 没有意义而不是 format , 因为 Format相比之下非常慢(进行大量递归模板实例化可能会很昂贵)。因此,在对类型进行操作时仍然需要使用模板元编程,但是如果您可以使用 CTFE 完成您需要做的事情,那通常会更好。

如果您正在寻找 Phobos 中的元编程工具, std.traitsstd.meta是主要的看点,尽管有些分散在 Phobos 中,具体取决于它们的用途(例如,特定范围的位于 std.range.primitives 中)。

此外,与混入字符串的方式类似,您可以混入模板。例如
template foo(T)
{
T i;
}

void main()
{
mixin foo!int;
auto a = i;
}

因此,由模板生成的代码本质上会被复制粘贴到您将其混合的位置。或者,您可以输入 mixin在模板声明上,使将其用作混入以外的任何东西都是非法的。例如
mixin template foo(T)
{
T i;
}

就个人而言,我通常只使用字符串混合来处理这类事情,但有些人更喜欢模板混合。

关于templates - dlang 模板和模板化类、结构和函数之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48126829/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com