使用模板指定一个函数,该模板接受并返回任意类

时间:2016-11-21 03:17:47

标签: oop templates d

我有兴趣定义一个给定类变量的函数,生成一个具有随机选择的成员属性的类对象的新实例。

上下文:考虑某个类circle1的实例Circle,其属性为colorradius。这些属性分别指定为red5的值。有问题的函数mutate必须接受circle1作为参数,但拒绝非类参数。

对于其他数据类型,模板在此上下文中提供答案。也就是说,模板可用于指定可接受多种类型参数的函数的通用实例。

如何使用模板定义接受(并返回)任何类实例的泛型函数?

1 个答案:

答案 0 :(得分:2)

通常,如果您需要限制模板可以采用的内容,则使用模板约束。 e.g。

import std.traits : isIntegral;

auto foo(T)(T t)
    if(isIntegeral!T)
{
    ...
}

import std.functional : binaryFun;

auto foo(alias pred, T, U)(T t, U u)
    if(is(typeof(binaryFun!pred(t, u.bar())) == bool)
{
    ...
}

只要在编译时检查条件,就可以测试几乎任何东西。并且它也可以用于函数重载(例如std.algorithm.searching.find具有相当多的重载,所有这些重载都通过模板约束来区分)。内置的__traitsstd.traits中的同名模板和is expressions提供了相当多的工具,用于在编译时测试内容,然后在模板约束中使用该信息或{{3}条件。

如果您特别想测试某些内容是否为某个类,请使用is表达式== class。 e.g。

auto foo(T)(T t)
    if(is(T == class))
{
    ...
}

一般情况下,您可能希望使用更具体的条件,例如__traits(compiles, MyType result = t.foo(22))is(typeof(t.foo(22)) == MyType)。所以,你可以有像

这样的东西
auto mutate(T)(T t)
    if(is(T == class) &&
       __traits(compiles, t.color = red) &&
       __traits(compiles, t.radius = 5))
{
    ...
}

如果条件是您想要重复使用的,那么创建一个同名模板是有意义的 - 这就是Phobos在static ifstd.range.primitives等地方所做的事情。例如,要测试输入范围,std.range.traits看起来像

template isInputRange(R)
{
    enum bool isInputRange = is(typeof(
    {
        R r = R.init;     // can define a range object
        if (r.empty) {}   // can test for empty
        r.popFront();     // can invoke popFront()
        auto h = r.front; // can get the front of the range
    }));
}

然后需要输入范围的代码可以使用它。因此,Phobos中的许多功能都有像

这样的东西
auto foo(R)(R range)
    if(isInputRange!R)
{
    ...
}

一个更具体的例子就是std.range.primitives.isInputRange的重载:

InputRange find(alias pred = "a == b", InputRange, Element)
               (InputRange haystack, Element needle)
    if(isInputRange!InputRange &&
       is(typeof(binaryFun!pred(haystack.front, needle)) : bool))
{
    ...
}
<>>AliÇehreli的书find,有几个相关的章节,包括:

Programming in D
http://ddili.org/ders/d.en/templates.html
http://ddili.org/ders/d.en/cond_comp.html
http://ddili.org/ders/d.en/is_expr.html