I have an object that sole responsability is to hold a value. This value can be passed in directly via constructor, or the constructor can take an anonymous function which tells the object how to get the value.
type
TDefineCached<T> = Reference to function: T;
TValue<T> = class(TInterfacedObject, IValue<T>)
private
FValue: T;
FActive: Boolean;
FDefine: TDefineCached<T>;
procedure DoDefine;
public
constructor Create(const Define: TDefineCached<T>);
class function New(const Define: TDefineCached<T>): IValue<T>; overload;
class function New(const Value: T): IValue<T>; overload;
function Value: T;
end;
That anonymous function will be executed only the first time the value is required, and that value will then be cached to be returned in further calls. This is working as expected in all but one situations, described bellow:
private
FCoordinate: IValue<Double>;
// some other code
function TGeoCoordinate.ToStringValue: IValue<string>;
var
s: string;
begin
s := FCoordinate.Value.ToString;
Result := TValue<string>.New(s);
end;
This code will work perfectly as expected.
Since FCoordinate is itself an IValue, FCoordinate.Value
will return a Double primitive. So when used in conjuntion with D10's native record helper for Double, FCoordinate.Value.ToString
will return a primitive string, which s
will hold.
Then, one of the overloads of TValue<string>.New
will accept a primitive string value, and s
goes right there in that alley.
All fine.
But, that s
variable is, or should be, optional. It will only be used once, so we could (should) be able to replace it with the expression itself.
But when I do this:
function TGeoCoordinate.ToStringValue: IValue<string>;
begin
Result := TValue<string>.New(FCoordinate.Value.ToString);
end;
The compiler will return [dcc32 Error] E2250 There is no overloaded version of 'New' that can be called with these arguments
.
While trying to detect the problem, I noticed this will work fine as well:
function TGeoCoordinate.ToStringValue: IValue<string>;
begin
Result := TValue<string>.New((FCoordinate.Value.ToString));
end;
Adding an extra pair of parentesis to the expression will force it to evaluate the full expression FCoordinate.Value.ToString
, and TValue.New will no longer fail.
Nevertheless, I do believe this shouldn't be necessary.
I then tried creating another implementation of IValue, where the class function New is not overloaded, and only accepts a T value, and this also works fine, which means somewhere the compiler is being deceived by the overloaded version of New
which accepts an anonymous function.
Could this be a compiler bug, or am I missing something in this picture?
I have tried to search for similar problems, but couldn't fine any search terms that could filter it enough, as this problem uses fairly generic wording.