2016-11-21 46 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

相關問題