Discussion:
Converting records back and forth. (Forward declarations for records needed ?!?)
(too old to reply)
Skybuck Flying
2011-09-19 10:12:43 UTC
Permalink
Hello,

I want to write code as follows and I will simplify it here to illustrate
the problem.

Let's say I want to kinds of records: TrecordA and TrecordB.

I want to be able to convert types of TrecordA to TrecordB but I also want
to be able to convert types of TrecordB to TrecordA.

So I was thinking of writing code as follows:

type
TrecordA = record
function ToRecordB : TrecordB;
end;

TrecordB = record
function ToRecordA : TrecordA;
end;

These two functions would return a value type/a copy of itself but
converted.

However there is ofcourse a problem, there is a circular reference, and as
far as I know delphi or free pascal cannot forward declare records ?

I could use forward pointers perhaps, but that would be a bit weird and
might lead to bugs because of automatic stack variables/value types being
automatically cleaned up, using pointers would pretty much dismiss the value
types, I could also use dynamic memory but this would create further
problems, since records do no have destructors, the last possible option is
using classes instead of records, so then class forward declarations could
be used, but the records are kinda simply and classes is probably a bit
overkill.

So to me it seems this basic functionality that I seek seems to be missing
from the object pascal/delphi language, so perhaps it can be added to a
future version ?

Bye,
Skybuck.
Skybuck Flying
2011-09-19 10:31:21 UTC
Permalink
There appears to be a solution in Delphi for this:

It's called "record helpers":

Demonstration program:

// *** Begin of Test Program ***

program TestProgram;

{$APPTYPE CONSOLE}

{

Test circular records problem and solutions.

version 0.01 created on 19 september 2011 by Skybuck Flying

The solution below uses a "record helper" which seems to solve it nicely
and now I can write the code the way I want to...

Not sure if it compiles in free pascal, but it does compile in Delphi XE at
least ;)

(Perhaps another solution could be to use type casting, but that would not
solve
the circular problem, so not going to test that)

}

uses
SysUtils;

type
TrecordB = record
private
mData : double;
public
property Data : double read mData write mData;
end;

TrecordA = record
private
mData : integer;
public
property Data : integer read mData write mData;

function ToRecordB : TrecordB;
end;

// solution: record helper
TrecordBhelper = record helper for TrecordB
private
// mData : double;
public
// property Data : double read mData write mData; // must be in TrecordB
apperently ?!?

function ToRecordA : TrecordA;
end;

function TrecordA.ToRecordB : TrecordB;
begin
result.mData := mData;
end;


function TrecordBhelper.ToRecordA : TrecordA;
begin
result.mData := Round(mData);
end;

procedure Main;
var
vRecordA : TrecordA;
vRecordB : TrecordB;
begin
writeln('program started');

vRecordA.mData := 555;
vRecordB.mData := 666.666;

writeln( 'vRecordA.mData: ', vRecordA.mData );
writeln( 'vRecordB.mData: ', vRecordB.mData );

writeln( 'vRecordA.ToRecordB.mData: ', vRecordA.ToRecordB.mData );
writeln( 'vRecordB.ToRecordA.mData: ', vRecordB.ToRecordA.mData );

writeln('program finished');
end;

begin
try
Main;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
ReadLn;
end.


// *** End of Test Program ***

Bye,
Skybuck.
Skybuck Flying
2011-09-19 10:43:28 UTC
Permalink
Hmm, interesting, the problem returns when TrecordA and TrecordB are each
put into their own units.

The problem turns from a "circular record" problem into a "circular unit"
problem :(

I guess only way to solve it is to place both types into the same unit ?

Or perhaps there is another way, perhaps the new unit extension mechanism...
hmm...

Bye,
Skybuck.
Skybuck Flying
2011-09-19 10:49:30 UTC
Permalink
Well for now it's not so much of a problem for me in my current project... I
can use a third class to do the conversions... but this is somewhat of an
interesting delphi language problem ;)

Bye,
Skybuck.

Loading...