在C ++中,您可以为模板化函数明确定义唯一的特化,例如(到steal an example)
// A generic sort function
template <class T>
void sort(T arr[], int size)
{
// code to implement Quick Sort
}
// Template Specialization: A function
// specialized for char data type
template <>
void sort<char>(char arr[], int size)
{
// code to implement counting sort
}
有没有办法用Delphi泛型方法做等效的工作?当我尝试
function TryStrConv<T>(S: string; var Val: T): boolean;
function TryStrConv<float>(S: string; var Val: float): boolean;
我收到有关如何使用Overload
指令的警告。
我希望获得的是一种编写泛型TryStrConv
的方法,其中默认实例化返回false并且什么都不做,而int和float实例化,我想明确提供,使用{ {1}}和TryStrToInt
。或者,如果我在德尔福有一个通用的转换工具,我很想知道它。
感谢。
答案 0 :(得分:5)
您无法在声明中填写泛型参数。您可以使用一个泛型方法重载,也可以使用一个不通用的方法:
function TryStrConv<T>(S: string; var Val: T): boolean; overload;
function TryStrConv(S: string; var Val: Extended): boolean; overload;
但需要注意的是,它只选择Extended的非泛型,而不是Delphi的其他浮点类型,如Double或Single。
另一种方法是,如果您使用的是Delphi XE7或更高版本,则可以使用新的内部函数来分支泛型方法实现(它会在编译时解析,并且会消除未执行的路径)。例如,它可能看起来像这样(我省略了TryStrConv方法的类型,但是你知道在Delphi中你不能有通用的独立例程,但它们必须是某种类型的方法,即使只是静态的):
function TryStrConv<T>(S: string; var Val: T): boolean;
begin
if GetTypeKind(T) = tkFloat then
begin
// do stuff with val being a float type, still need to handle the different float types though
case GetTypeData(TypeInfo(T)) of
ftDouble: DoStuffWithDouble;
// if you need to pass Val here you might need to do some pointer
// ref/deref hardcasts like PDouble(@Val)^ because otherwise you
// are not allowed to cast type T to Double (or any other type)
....
end;
else
Result := False;
end;
答案 1 :(得分:0)
你可以做类似的事情:
Type
TCalc = record
class function TryStrConv(S: string; var Val: Double): boolean; overload; static;
class function TryStrConv(S: string; var Val: integer): boolean; overload; static;
class function TryStrConv<T>(S: string; var Val: T): boolean; overload; static;
end;
{ TCalc }
class function TCalc.TryStrConv(S: string; var Val: Double): boolean;
begin
Result := TryStrToFloat(s,Val);
end;
class function TCalc.TryStrConv(S: string; var Val: integer): boolean;
begin
Result := TryStrToInt(S,Val);
end;
class function TCalc.TryStrConv<T>(S: string; var Val: T): boolean;
begin
Result := false;
end;
并测试:
var
iVal : Integer;
dVal : Double;
sVal : String;
ok : Boolean;
begin
ok := TCalc.TryStrConv('12',iVal);
WriteLn(ok,' ',iVal); // True 12
ok := TCalc.TryStrConv('12',dVal);
WriteLn(ok,' ',dVal); // True 1.2 E+1
ok := TCalc.TryStrConv('12',sVal);
WriteLn(ok,' ',sVal); // False
ReadLn;
end.
正如Stefan所说:你必须为每个浮点类型编写一个特定的函数。