Delphi D10 Seattle's built-in expression parser unable to evaluate an expression under certain conditions

I have an object that is only responsible for storing a value. This value can be passed directly through the constructor, or the constructor can use an anonymous function that 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;

      

This anonymous function will only be executed the first time a value is needed, and this value will then be cached to be returned on subsequent calls. This works as expected in all but one case described below:

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 fine as expected. Since FCoordinate is itself an IValue, FCoordinate.Value

returns a double primitive. Therefore, when used in conjunction with the built-in D10 write helper for Double, it FCoordinate.Value.ToString

will return a primitive string to be held s

. Then one of the overloads TValue<string>.New

will take a primitive string value, and s

- right in that alley. All perfectly.

But that variable s

is or should be optional. It will only be used once, so we could (should) 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

.

When trying to spot the problem, I noticed that this would work perfectly:

function TGeoCoordinate.ToStringValue: IValue<string>;
begin
  Result := TValue<string>.New((FCoordinate.Value.ToString));
end;

      

Adding an extra pair of parent expressions to the expression will force it to evaluate the full expression FCoordinate.Value.ToString

and TValue.New will no longer fail.

However, I believe this is not necessary.

Then I tried to create another implementation of IValue where the function of the New class is not overloaded and only accepts the value of T, and this also works great, which means that somewhere the compiler is fooled by an overloaded version New

that accepts an anonymous function.

Could this be a compiler error or am I missing something in this snapshot?

I tried to find similar problems, but couldn't work out any search terms that might filter it enough, as this problem uses a fairly general wording.

+3


source to share





All Articles