我有一个结构体 Foo!T
和一个对任意两个 Foo!T
进行操作的函数。
我希望声明这样一个函数
void fun(U)(U a, U b) if (is(U : Foo!T, T...)) { }
但是,事实证明我可以将其声明为
void fun(U)(U a, U b) if (is(U : Foo)) { }
仅当我在 Foo
的内部声明它。
例如:
struct Foo(T) {
void fun1(U)(U b) if (is(U : Foo)) { }
}
void fun2(U)(U a, U b) if (is(U : Foo)) { }
unittest {
Foo!int f;
f.fun1(f);
f.fun2(f);
}
以上失败,并在调用时使用struct d.Foo(T) 作为类型
有趣2。不过,fun1
没问题。
为什么约束 is(U : Foo)
在 Foo
体内有效,但无效
外部?
Foo
体内的比较 is(U : Foo)
是否等同于 is(U :
Foo!V, V...)
在 Foo
的主体之外?
最佳答案
在模板类型内部,模板的名称指的是模板的特定实例化,除非明确给出了不同的实例化。例如,
struct Foo(T)
{
pragma(msg, Foo.stringof);
}
pragma(msg, Foo.stringof);
void main()
{
Foo!int foo1;
Foo!string foo2;
}
打印
Foo(T)
Foo!int
Foo!string
打印的第一个编译指示是紧随模板之后的编译指示,另外两个编译指示是在实例化 Foo
时生成的。这使得当您引用它时(例如,当从成员函数返回它时),您不必在结构声明内的所有地方粘贴 Foo!T
。如果类型具有多个而不是只有一个模板参数,则这一点特别有用。但这确实意味着如果您想引用通用模板,您要么需要使用特定参数实例化它 - 例如在 Foo
内部使用 Foo!int
来引用 Foo!int
,无论当前实例是什么 - 或者您需要使用点运算符表明您希望来自外部作用域的 Foo
。例如
struct Foo(T)
{
pragma(msg, Foo.stringof);
pragma(msg, .Foo.stringof);
}
pragma(msg, Foo.stringof);
void main()
{
Foo!int foo1;
Foo!string foo2;
}
打印
Foo(T)
Foo!int
Foo(T)
Foo!string
Foo(T)
因此,当在模板类型中编写诸如模板约束之类的内容时,请注意在 struct Foo(T)
或 class Foo( T)
表示特定实例化,而不是模板本身。
另外,如果您正在专门测试 U
是否是 Foo
的实例,我建议使用 std.traits.isInstanceOf
- 例如if(isInstanceOf(Foo, U))
。可以说,它确实应该是 isInstantiationOf
而不是 isInstanceOf
,但无论如何,它以比使用裸露 is
表达式更惯用的方式完成这项工作。
关于templates - 模板比较在模板体内发生变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36222313/