2016-11-21 13 views
1

我有兴趣定义一个给定类变量的函数,用随机选择的成员属性生成一个类对象的新实例并进行变异。指定一个带有模板并返回任意类的函数

语境:考虑一个实例,circle1,一些类,Circle,拥有属性colorradius。这些属性分别被赋予值red5。有问题的函数mutate必须接受circle1作为参数,但拒绝非类参数。

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

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

回答

2

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

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.traitsis expressions中的同名模板提供了很多工具,用于在编译时测试内容,然后在模板约束或static if条件下使用该信息。

如果您特别想测试某种类是否是某种类型,请使用is表达式与== class。例如

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)) 
{ 
    ... 
} 

如果条件是要重复使用的东西,那么它可以是有意义的创建一个同名的模板 - 这是什么在火卫一进行的地方,如std.range.primitivesstd.range.traits。例如,要测试的输入范围,std.range.primitives.isInputRange看起来像

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 
    })); 
} 

然后代码需要的输入范围可以使用。所以,很多功能在火卫一有这样的东西

auto foo(R)(R range) 
    if(isInputRange!R) 
{ 
    ... 
} 

更具体的例子是该超载find

InputRange find(alias pred = "a == b", InputRange, Element) 
       (InputRange haystack, Element needle) 
    if(isInputRange!InputRange && 
     is(typeof(binaryFun!pred(haystack.front, needle)) : bool)) 
{ 
    ... 
} 

阿里Çehreli的书,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
http://ddili.org/ders/d.en/templates_more.html

相关问题