一般に、テンプレートに適用できるものを制限する必要がある場合は、テンプレート制約を使用します。例えば
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
は、テンプレート制約によって区別されるオーバーロードがかなりあります)。組み込みの__traits
、std.traits
、is
expressionsという名前のテンプレートは、コンパイル時にテストし、その情報をテンプレートの制約やstatic if
の条件で使用するためのツールを提供します。
具体的に何かがクラスかどうかをテストする場合は、== class
のis
式を使用します。例えば一般的に
auto foo(T)(T t)
if(is(T == class))
{
...
}
しかし、あなたはおそらく、このような__traits(compiles, MyType result = t.foo(22))
やis(typeof(t.foo(22)) == MyType)
など、より具体的な条件を使用することをお勧めします。 std.range.primitivesとstd.range.traitsのような場所でフォボスで行われているものである - だから、あなたは条件があなたが再利用したいものである場合、それは同名のテンプレートを作成するために意味をなすことができ
auto mutate(T)(T t)
if(is(T == class) &&
__traits(compiles, t.color = red) &&
__traits(compiles, t.radius = 5))
{
...
}
のようなものを持つことができます。例えば、入力範囲をテストするために、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