4

テンプレートを読む-再考:

struct S(T : T*) {
  T t;  // t is supposed to be of type 'int*', but it's of type 'int', why?
}

void main() {

  int x = 123;
  S!(int*) s;
  static assert(is(typeof(s.t) == typeof(&x)));
}

上記のコードはコンパイルされません。

不思議なことに、以下はコンパイルされます。

struct S(T : int*) {
  T t;
}

void main() {

  int x = 123;
  S!(int*) s;
  static assert(is(typeof(s.t) == typeof(&x)));
}

私はこの振る舞いを理解していません。説明をいただければ幸いです。

4

2 に答える 2

5

型の特殊化 (コロンの後の型) がパラメーター識別子 ( など) に依存している場合、結果の識別子は、一致があった場合、型の特殊化 (推定されT : T*た型) における識別子 ( ) の役割を参照します。T

それ以外の場合、特殊化が のように独立している場合T : int*、結果の識別子は型特殊化のエイリアスになります。

例:

=========================================================
Argument T        | Specialization     | Result
=========================================================
void              | T : void           | void
char              | T : void           | <no match>
int*              | T : T*             | int
immutable(char)[] | T : T[]            | immutable(char)
immutable(char)[] | T : immutable(T)[] | char
=========================================================

テンプレート パラメーターに渡される引数に不一致がある場合、テンプレートはオーバーロード セットから削除されます。一致が見つかる前にオーバーロード セットが空になると、エラーが発生します。

IsExpression (一次式) に不一致がある場合is(...)、結果は false になり、シンボルはスコープに導入されません。

于 2012-04-13T19:20:32.233 に答える
3

http://dlang.org/template.htmlの Argument Deduction セクションで説明されているように、テンプレート引数の型を推測する場合:

  1. パラメーターの型の特殊化がない場合、パラメーターの型はテンプレート引数に設定されます。
  2. 型の特殊化が型パラメーターに依存している場合、そのパラメーターの型は型引数の対応する部分に設定されます。
  3. すべての型引数を調べた後、型が割り当てられていない型パラメーターが残っている場合は、TemplateArgumentList の同じ位置にあるテンプレート引数に対応する型が割り当てられます。
  4. 上記の規則を適用しても、各テンプレート パラメーターの型が正確に 1 つにならない場合は、エラーになります。

そして、あなたのケースに対応する例は次のとおりです。

template TBar(T : T*) { }
alias TBar!(char*) Foo3;   // (2) T is deduced to be char

したがって、最初の例で見ているのは、予想される動作です。Tは両側にあるため、T最終的にテンプレート引数が になるように評価されT*ます。したがって、テンプレート引数はint*であるため、T*になりint*、最終的に になりTますint。あなたが持っているものは非常に似ていstd.traits.pointerTargetます:

/**
Returns the target type of a pointer.
*/
template pointerTarget(T : T*)
{
    alias T pointerTarget;
}

2 番目の例は、そのテンプレートがT暗黙的に に変換可能であることを要求しているため、コンパイルされint*ます。また、暗黙的にそれ自体に変換できるため、テンプレート引数としてint*渡すと機能します。int*問題を引き起こしているTのは、式の右側が左側に依存しているため、 が両側にある場合です。

さて、ここで実際にテストしようとしているのは、テンプレート引数がポインターであることだと思いますか? その場合は、次を使用する必要がありますstd.traits.isPointer

struct S(T)
    if(isPointer!T)
{
    T t;
}
于 2012-04-13T18:43:46.323 に答える