DLang - 模板约束 - 类型必须实现接口

时间:2015-06-30 16:44:41

标签: templates constraints d

我正在尝试将以下C#代码转换为D,但是我无法弄清楚如何使模板约束起作用。

C#实施

public interface IComponent
{

} 

public class Container
{
    public T CreateComponent<T>() where T: IComponent, new()
    {
        // Trivial initialisation for example
        var t = new T(); 
        return t;
    }
}

D实施

public interface Component
{

}

public class Container
{
    public T createComponent(T)()
    {
        // Trivial initialisation for example
        auto t = new T();
        return t;
    }
}

如何重新创建“where T:IComponent”约束?

我尝试过将is,typeof等组合在一起的各种表达方式,但找不到有效的方法。

3 个答案:

答案 0 :(得分:4)

好吧,如果您尝试做的只是要求T实施接口IComponent,那么is(T : IComponent)将测试T是否可以隐式转换为IComponentIComponentT的基类或它实现的接口时的情况。所以,你最终会得到像

这样的东西
public class Container
{
    public T createComponent(T)()
        if(is(T : IComponent))
    {
        // Trivial initialisation for example
        auto t = new T();
        return t;
    }
}

现在,从技术上讲,如果alias this用于定义隐式转换,其他内容可以匹配,这不太常见,但如果你对它更偏执,那么你可以使约束也检查T是否为类 - is(T == class)

public class Container
{
    public T createComponent(T)()
        if(is(T == class) && is(T : IComponent))
    {
        // Trivial initialisation for example
        auto t = new T();
        return t;
    }
}

然后,T必须是一个类,它必须隐式转换为IComponent。但是, 在技术上仍然可以使T成为一个没有实现IComponent的类,但确实定义了一个转换为{alias this的{​​{1}} {1}}(IComponent不再可能成为执行此操作的结构体)。所以,它并不完美,但我不知道如何通过继承而不是T来确保隐式转换。所以,遗憾的是,我不知道如何绝对保证alias this是一个实现T的类。我知道如何做的最多是确保它隐式转换为`IComponent,几乎总是意味着它实现它。

然而,问题的实际情况是,在绝大多数情况下,只需检查IComponent就足够了,并且根据代码的编写方式,它甚至可以使用隐式转换为{的类型。 {1}}但实际上并非is(T : IComponent)。因此,IComponent在工作中抛出扳手的事实可能实际上不是问题。但是,通常,IComponent是通用代码的祸根,也是大多数通用代码不应检查隐式转换的原因。对于类型来说,通过alias this隐式转换但实际上没有在函数中转换它太容易了,在这种情况下,它要么不会编译,要么它可能有奇怪的行为,如果它支持与目标类型相同的操作,但这些操作与原始类型实际转换为目标类型时的结果不同。因此,如果您在模板化代码中实际想要隐式转换,则应通过将参数分配给目标类型来强制进行隐式转换。但是,由于您通常希望测试接口而不是隐式转换,因此您可能需要的是一个测试,在不允许通过alias this进行隐式转换的情况下对其进行测试。不幸的是,我知道在编译时检查一种类型是从另一种类型派生还是实现特定接口的唯一方法是检查它是否隐式转换为该基类或接口。

但也许有一些有趣的伏都教有着真正能够做到这一点的特质。如果有的话,我们应该为std.traits添加一些东西来为你做这些,如果没有,也许我们应该找到一种方法来添加它,因为如果你alias this肯定会烦人的话不想要它。但幸运的是,大多数代码都没有出现问题,如果您没有编写公共API,那么只有在使用{{{{{{{{{{{{{{{{{ 1}}。如果你不是,那真的没关系。

答案 1 :(得分:3)

您甚至不需要模板约束,只需要模板专业化:

T createComponent(T : IComponent)() { /* some code */ }

答案 2 :(得分:1)

以典型的方式,我在问http://ddili.org/ders/d.en/is_expr.html

之后找到答案
public T addComponent(T)()
    if (is(T: Component))