2

Andrei Alexandrescu による Dの優れた 3 つの可能性が低い機能を参照した後、次のように、そこで与えられた回文アルゴリズムをテストしました。

import std.exception;

bool isPalindrome(T)(T[] a)
{
  for (; a.length > 1; a = a[1 .. $-1]) {
    if (a[0] != a[$-1]) {
      return false;
    }
  }
  return true;
}

bool isPalindrome(Range)(Range r)
{
  for (; !r.empty; r.popFront(), r.popBack()) {
    if (a.front != a.back) {
      return false;
    }
  }
  return true;
}

unittest {
  enforce(isPalindrome("dallassallad"));
}

配列バージョンは文字列に対して正常に機能しますが、範囲バージョンを同じコンパイル ユニットに追加すると、DMD (2.062) が文句を言います:

palindrome.d(31): Error: template palindrome.isPalindrome matches
more than one template declaration,
palindrome.d(10):isPalindrome(T)(T[] a) and
palindrome.d(20):isPalindrome(Range)(Range r)

私の推測では、配列のケースを含まないように範囲の使用を制限することです。それ、どうやったら出来るの?

アレイバージョンを削除することもテストしましたが、エラーが発生しました

/home/per/Work/cognia/palindrome.d(22): Error: no property 'empty' for type 'string'
/home/per/Work/cognia/palindrome.d(22): Error: undefined identifier 'popFront'
/home/per/Work/cognia/palindrome.d(22): Error: undefined identifier 'popBack'
/home/per/Work/cognia/palindrome.d(23): Error: undefined identifier a, did you mean variable r?
/home/per/Work/cognia/palindrome.d(23): Error: undefined identifier a, did you mean variable r?
/home/per/Work/cognia/palindrome.d(27): Warning: statement is not reachable
/home/per/Work/cognia/palindrome.d(31): Error: template instance palindrome.isPalindrome!(string) error instantiating

奇妙だと思う配列では、範囲バージョンが機能しないようです。

何をすべきか?

4

2 に答える 2

6

次のように、2 番目のテンプレートにテンプレート制約を追加します。

bool isPalindrome(Range)(Range r)
    if (!isArray!Range)

テンプレートをインポートする必要がありますstd.traitsisArray

2 番目のテンプレートのみを使用する場合は、 (Uniform Function Call Syntax) をstd.array使用するものをインポートして、配列が、、などの機能を持つようにする必要があります。UFCSfrontpopFrontempty

UFCS は基本的に次のことを意味します。

int[] x;
int f = x.front;

に翻訳されます:

int f = front(x);

frontその他は、 の配列に対して定義されていますstd.array。これにより、配列を範囲であるかのように使用できます。独自の型に対して同じ手法を使用できます。範囲関数はfront、構造体/クラス内などで定義するか、構造体/クラスを最初のパラメーターとして受け取る関数として外部で定義できます。

詳細については、std.rangeのドキュメントを参照してください。

于 2013-01-22T23:08:09.200 に答える
5

また、空の範囲を縮小しようとする可能性があるため、汎用バージョンには厄介なバグがあることに注意してください。修正版は次のとおりです。

bool isPalindrome(Range)(Range r)
{
    while (!r.empty) {
        if (a.front != a.back) {
          return false;
        }
        r.popFront();
        if (r.empty) {
            return true;
        }
        r.popBack();
    }
    return true;
}
于 2013-01-23T12:46:49.193 に答える