2

在看过Andrei Alexandrescu 的 D 的三个不太可能成功的优秀特征之后,我测试了那里给出的回文算法,如下所示

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

像这样向第二个模板添加模板约束:

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

您将需要导入模板std.traitsisArray

如果您只想使用第二个模板,则必须导入std.array使用UFCS(统一函数调用语法)以使数组具有frontpopFrontempty等功能。

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 回答