如在http://dlang.org/template.html的参数推导部分解释,推断类型的模板参数时:
- If there is no type specialization for the parameter, the type of the parameter is set to the template argument.
- If the type specialization is dependent on a type parameter, the type of that parameter is set to be the corresponding part of the type argument.
- If after all the type arguments are examined there are any type parameters left with no type assigned, they are assigned types corresponding to the template argument in the same position in the TemplateArgumentList.
- If applying the above rules does not result in exactly one type for each template parameter, then it is an error.
和对应于你的情况的例子是:
template TBar(T : T*) { }
alias TBar!(char*) Foo3; // (2) T is deduced to be char
所以,你在你的第一个例子中看到的是预期的行为。由于T
位于两侧,因此T
最终会被评估为导致模板参数为T*
的结果。因此,由于模板参数为int*
,因此T*
将为int*
,并且T
最终为int
。你有什么非常相似std.traits.pointerTarget
:
/**
Returns the target type of a pointer.
*/
template pointerTarget(T : T*)
{
alias T pointerTarget;
}
你的第二个例子中编译,因为模板要求T
是隐式转换为int*
。而且由于int*
可以隐式转换为自己,因此当您将int*
作为模板参数传递时,它可以工作。什么导致你的问题是当两边都有T
时,因为表达式的右边是依赖于左边的。
现在,我假设你实际打算在这里测试的是模板参数是一个指针?如果是这样的话,那么就应该使用std.traits.isPointer
:
struct S(T)
if(isPointer!T)
{
T t;
}
如果你尝试'struct S(T:void *)' – 2012-04-13 18:11:17
我会指出那些断言不会工作(当然,它们不在2.059上),因为你不能比较类型。你需要他们是一个'is'表达式。 – 2012-04-13 18:32:07
@JonathanMDavis无论如何,在第一个例子中执行's.t =&x'不起作用,并且我得到了'错误:不能隐式地将int *类型的表达式(&x)转换为int'。所以我想这是一个DMD错误? – Arlen 2012-04-13 18:40:00