2016-11-21 5 views
1

クラス変数を指定して関数を定義し、ランダムに選択したメンバー属性を変更したクラスオブジェクトの新しいインスタンスを生成することに興味があります。任意のクラスを受け取り、返すテンプレートを持つ関数を指定する

コンテキスト:いくつかのクラス、Circleの、属性colorradiusがあり、例えば、circle1を考えてみましょう。これらの属性にはそれぞれ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の条件で使用するためのツールを提供します。

具体的に何かがクラスかどうかをテストする場合は、== classis式を使用します。例えば一般的に

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

しかし、あなたはおそらく、このような__traits(compiles, MyType result = t.foo(22))is(typeof(t.foo(22)) == MyType)など、より具体的な条件を使用することをお勧めします。 std.range.primitivesstd.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

関連する問題