模板主体内部的模板比较变化
Template comparison changes inside template body
我有一个结构 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) is used as a type
fun2
。 fun1
,不过还好。
为什么约束 is(U : Foo)
在 Foo
的主体内有效,但不是
外部?
Foo
体内的比较is(U : Foo)
是否等同于Foo
体外的is(U :
Foo!V, V...)
?
在模板化类型中,模板的名称指的是模板的特定实例化,除非明确指定了不同的实例化。例如,
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
打印的第一个 pragma 是紧跟在模板之后的,另外两个是 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)
中使用 Foo
将意味着特定的实例化和 不是模板本身。
此外,如果您要专门测试 U
是否是 Foo
的实例,我建议您使用 std.traits.isInstanceOf
- 例如if(isInstanceOf(Foo, U))
。可以说,它确实应该是 isInstantiationOf
而不是 isInstanceOf
,但无论如何,它以比使用裸露的 is
表达式更惯用的方式完成工作。
更具体地说,像
这样的模板
struct Foo(T) {}
扩展到等价物
template Foo(T)
{
struct Foo {}
}
原始模板引用自动转发给模板中与模板同名的成员:
Foo!int foo;
// expands to:
Foo!(int).Foo foo;
您可以使用它来制作出于某种原因需要的 "hidden" 模板成员。例如,std.typecons.Tuple
使用了这种技术:它在 Tuple
模板中定义了一些辅助模板和函数,然后定义了 Tuple
结构。但是您可以像使用模板结构一样使用它。
我有一个结构 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) is used as a type
fun2
。 fun1
,不过还好。
为什么约束 is(U : Foo)
在 Foo
的主体内有效,但不是
外部?
Foo
体内的比较is(U : Foo)
是否等同于Foo
体外的is(U :
Foo!V, V...)
?
在模板化类型中,模板的名称指的是模板的特定实例化,除非明确指定了不同的实例化。例如,
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
打印的第一个 pragma 是紧跟在模板之后的,另外两个是 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)
中使用 Foo
将意味着特定的实例化和 不是模板本身。
此外,如果您要专门测试 U
是否是 Foo
的实例,我建议您使用 std.traits.isInstanceOf
- 例如if(isInstanceOf(Foo, U))
。可以说,它确实应该是 isInstantiationOf
而不是 isInstanceOf
,但无论如何,它以比使用裸露的 is
表达式更惯用的方式完成工作。
更具体地说,像
这样的模板struct Foo(T) {}
扩展到等价物
template Foo(T)
{
struct Foo {}
}
原始模板引用自动转发给模板中与模板同名的成员:
Foo!int foo;
// expands to:
Foo!(int).Foo foo;
您可以使用它来制作出于某种原因需要的 "hidden" 模板成员。例如,std.typecons.Tuple
使用了这种技术:它在 Tuple
模板中定义了一些辅助模板和函数,然后定义了 Tuple
结构。但是您可以像使用模板结构一样使用它。