4
struct S(int a, int b) { }

void fun(T)(T t) { }

fun一緒に働きたいSだけです。署名制約はどのようになりますか?

fun私はのメンバーを作ることができませんS、そして私と一緒void fun(T)(T t) if(is(T : S)) { }Error: struct t1.S(int a,int b) is used as a type

4

3 に答える 3

10

Sタイプではありません。型のテンプレートです。S!(5, 4)タイプです。の異なるインスタンス化が完全に異なるコードをS生成する可能性は十分にあるため、の定義はとは完全に異なる可能性があります。たとえば、S!(5, 4)S!(2, 5)S

struct S(int a, int b)
{
    static if(a > 3)
        string foo;

    static if(b == 4)
        int boz = 17;
    else
        float boz = 2.1;
}

S!(5, 4)メンバー変数の数とタイプが異なるため、の代わりにinを実際に使用できないことに注意してくださいS!(2, 5)。それらは、名前が付けられた構造体であり、実際に相互に持つすべての関係についてまったくテンプレート化されUていない可能性があります。V

現在、特定のテンプレートのさまざまなインスタンス化は、APIに関しては一般的に類似しています(または、おそらく同じテンプレートでは実行されなかったでしょう)が、コンパイラーの観点からは、相互に関係はありません。したがって、これを処理する通常の方法は、名前やインスタンス化元のテンプレートではなく、純粋に型のAPIに制約を使用することです。

したがって、S関数foo、、、およびが必要でbarあり、それらの関数を使用する場合は、指定された型にこれらの関数があり、期待どおりに機能することをテストする制約を作成します。例えばfoozlefunfun

void fun(T)(T t)
    if(is({ auto a = t.foo(); t.bar(a); int i = t.foozle("hello", 22);}))
{}

次にfoo、値を返すという関数、値を返す場合と返さbarない場合があり、の結果をfoo受け取るという名前の関数、およびaとanfoozleを取り、を返すという名前の関数を持つ型は、でコンパイルされます。したがって、のインスタンス化のみを行うことを主張した場合よりもはるかに柔軟性があります。ほとんどの場合、そのような制約は、生のコードを入れて再利用可能(そしてよりユーザーフレンドリー)にするのではなく、別々の同名のテンプレート(または)に分けられますが、そのような式は、そのような同名のテンプレートが内部で使用するものです。stringintintfunfunSisForwardRangeisDynamicArrayis expression

さて、のインスタンス化でのみ機能するように制約することを本当に主張する場合、私が知っている2つのオプションがあります。funS

1.常に持つある種の宣言を追加し、S他のタイプが持つことを期待しないでください。例えば

struct S(int a, int b)
{
    enum isS = true;
}

void fun(T)(T t)
    if(is(typeof(T.isS)))
{}

宣言の実際の値は重要ではないことに注意してください(そのタイプも重要ではありません)。あなたがテストしているのはそれが存在するという単純な事実です。

2.よりエレガントな(しかし、それほど明白ではない解決策)は、これを行うことです。

struct S(int a, int b)
{
}

void fun(T)(T t)
    if(is(T u : S!(i, j), int i, int j))
{}

isは、非常に複雑になるとブードゥーに接する傾向がありますが、コンマを使用したバージョンはまさに必要なものです。T uテストしているタイプと識別子です。これにより、インスタンス化する: S!(i, j)テンプレートの特殊化が提供されます。T残りはTemplateParameterList、左側のもので使用されているが、以前に宣言されていないシンボルを宣言することです-この場合、iおよびj

于 2012-07-07T22:14:56.907 に答える
7

他の回答には、いくつかの小さな赤いニシンがあると思います。次のように、パターン マッチングを使用して、T が S のインスタンスであるかどうかを判断できます。

最も簡単な方法は、引数自体をパターンマッチすることです:

void fun(int a, int b)(S!(a, b) t) {
}

より一般的には、テンプレート制約内で、分離のパターン マッチを行うことができます。

void fun(T)(T t) if (is(T U == S!(a, b), int a, int b)) {
}

どちらの場合も、インスタンス化引数にアクセスできます。

于 2012-07-26T16:23:25.623 に答える
3

"Work with Sonly"は D ではあまり意味がありません。なぜなら、 Sは型ではなく、template だからです。

テンプレートは、他の言語とは異なり、D ではそれ自体が「何か」です。

あなたが書いたものは次の省略形です:

template S(int a, int b) { struct S { } }

したがって、タイプの完全な名前はS(a, b).S、使用するものは何でもabです。「一般的に」参照する方法はありませんS

このような制約を入れる必要がある場合は、内部にプライベートなものを入れて、同じメンバーSを持っているかどうかを確認することをお勧めします。T

于 2012-07-07T20:46:24.920 に答える