4
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

4

3 回答 3

10

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拥有函数foobarfoozle,并且希望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. 在大多数情况下,这些约束被分离到单独的同名模板(例如isForwardRangeisDynamicArray)中,而不是将原始代码放在一个中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声明在左边的东西中使用但以前没有声明过的符号 - 在这种情况下,ij.

于 2012-07-07T22:14:56.907 回答
7

我认为其他答案中有一些小红鲱鱼。您可以使用模式匹配来确定 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)) {
}

在这两种情况下,您都可以访问实例化参数。

于 2012-07-26T16:23:25.623 回答
3

S仅使用”在 D 中实际上没有意义,因为 S它不是类型,而是模板

与其他语言不同,模板本身就是D 中的“东西”。

你写的是一个简写

template S(int a, int b) { struct S { } }

所以type的全名是S(a, b).S, 无论ab使用什么。没有办法让它“一般地”指S.

如果您需要设置这样的约束,我建议在里面放一些私有的东西S,并检查它T是否具有相同的成员。

于 2012-07-07T20:46:24.920 回答