struct S(int a, int b) { }
void fun(T)(T t) { }
我只想fun
合作S
。签名约束是什么样的?
我不能成为fun
的成员S
,并且void fun(T)(T t) if(is(T : S)) { }
我得到Error: struct t1.S(int a,int b) is used as a type
struct S(int a, int b) { }
void fun(T)(T t) { }
我只想fun
合作S
。签名约束是什么样的?
我不能成为fun
的成员S
,并且void fun(T)(T t) if(is(T : S)) { }
我得到Error: struct t1.S(int a,int b) is used as a type
S
不是类型。它是一种类型的模板。S!(5, 4)
是一种类型。很可能不同的实例化生成S
完全不同的代码,因此 的定义S!(5, 4)
可能与. 例如,可以是S!(2, 5)
S
struct S(int a, int b)
{
static if(a > 3)
string foo;
static if(b == 4)
int boz = 17;
else
float boz = 2.1;
}
请注意,成员变量的数量和类型不同,因此您不能真正使用 anS!(5, 4)
代替S!(2, 5)
. 它们也可能是命名的结构U
,并且V
对于它们彼此之间真正具有的所有关系根本没有被模板化。
现在,特定模板的不同实例化在其 API 方面通常是相似的(或者它们可能不会使用相同的模板完成),但从编译器的角度来看,它们彼此没有关系。因此,处理它的正常方法是仅在类型的 API 上使用约束,而不是在其名称或实例化模板上使用约束。
因此,如果您希望S
拥有函数foo
、bar
和foozle
,并且希望fun
使用这些函数,那么您将构建一个约束来测试给定的类型是否fun
具有这些函数以及它们是否按预期工作。例如
void fun(T)(T t)
if(is({ auto a = t.foo(); t.bar(a); int i = t.foozle("hello", 22);}))
{}
然后,任何类型如果有一个返回值的被调用foo
函数,一个bar
可能返回值或不返回值并接受结果的foo
命名函数,以及一个foozle
接受 astring
和 anint
并返回 an的函数,都int
将与 . 一起编译fun
。因此,fun
比您坚持只采用S
. 在大多数情况下,这些约束被分离到单独的同名模板(例如isForwardRange
或isDynamicArray
)中,而不是将原始代码放在一个中is expression
以便它们可重用(并且对用户更友好),但是这样的表达式是此类同名模板在内部使用的。
现在,如果你真的坚持限制fun
它只适用于 的实例化S
,那么我知道有两个选项。
1.添加某种类型的声明,它S
总是有并且你不希望任何其他类型有。例如
struct S(int a, int b)
{
enum isS = true;
}
void fun(T)(T t)
if(is(typeof(T.isS)))
{}
请注意,声明的实际值无关紧要(其类型也无关紧要)。这是一个简单的事实,即您正在测试它。
2.更优雅(但不太明显的解决方案)是这样做:
struct S(int a, int b)
{
}
void fun(T)(T t)
if(is(T u : S!(i, j), int i, int j))
{}
is
表达式一旦变得非常复杂,就会倾向于接近巫毒,但带逗号的版本正是您所需要的。T u
是您正在测试的类型和标识符;: S!(i, j)
给出您想要T
实例化的模板专业化;其余的是TemplateParameterList
声明在左边的东西中使用但以前没有声明过的符号 - 在这种情况下,i
和j
.
我认为其他答案中有一些小红鲱鱼。您可以使用模式匹配来确定 T 是否是 S 的某个实例,如下所示。
最简单的方法是仅对参数本身进行模式匹配:
void fun(int a, int b)(S!(a, b) t) {
}
更一般地,您可以在模板约束内进行模式匹配:
void fun(T)(T t) if (is(T U == S!(a, b), int a, int b)) {
}
在这两种情况下,您都可以访问实例化参数。
“S
仅使用”在 D 中实际上没有意义,因为
S
它不是类型,而是模板。
与其他语言不同,模板本身就是D 中的“东西”。
你写的是一个简写:
template S(int a, int b) { struct S { } }
所以type的全名是S(a, b).S
, 无论a
你b
使用什么。没有办法让它“一般地”指S
.
如果您需要设置这样的约束,我建议在里面放一些私有的东西S
,并检查它T
是否具有相同的成员。