Generics 字符串(数组)上回文算法的模板冲突
在看过优秀的文章之后,我测试了下面给出的回文算法Generics 字符串(数组)上回文算法的模板冲突,generics,d,palindrome,range,dmd,Generics,D,Palindrome,Range,Dmd,在看过优秀的文章之后,我测试了下面给出的回文算法 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
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
我觉得range版本不适合我觉得奇怪的数组
如何操作?向第二个模板添加模板约束,如下所示:
bool isPalindrome(Range)(Range r)
if (!isArray!Range)
您需要为isArray
模板导入std.traits
如果只想使用第二个模板,则必须导入std.array
,该模板使用UFCS
(统一函数调用语法)使数组具有front
、popFront
、empty
等功能
UFCS基本上意味着:
int[] x;
int f = x.front;
翻译成:
int f = front(x);
std.array
中的数组定义了front
和其他数组,这使您可以像使用范围一样使用数组。您可以对自己的类型使用相同的技术。可以在结构/类内部定义范围函数,例如front
,也可以在外部将其定义为将结构/类作为其第一个参数的函数
有关更多信息,请参阅文档。还请注意,通用版本中存在一个令人尴尬的错误,因为它可能试图减少空范围。更正版本为:
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;
}
还有
scope(exit)
和scope(failue)
在幻灯片中的向后位置(因此在回滚之前进行了清理),这是性能方面的问题,为了使数组与通用数组保持专用,您可以使用std.datetime
中的std.datetime
进行一些计时和比较。在汇编级别,通过所有优化和-inline,这两个函数最终可能是相同的。专门处理数组的函数使用切片,而通用函数使用辅助函数。但是,通用的方法更为正确,因为它可以正确地处理字符串范围(或字符串数组),因为front
调用可以正确地解码代码点,而专用的数组版本最终会比较代码单位。