Re: [fpc-pascal] Compatibility of very similar generic types

2016-08-18 Thread Sven Barth
Am 18.08.2016 15:09 schrieb "Felipe Monteiro de Carvalho" <
felipemonteiro.carva...@gmail.com>:
>
> On Thu, Aug 18, 2016 at 2:44 PM, Sven Barth 
wrote:
> > generic procedure WriteVector_To_DM(ADest: TDataManager; ASelf:
> > specialize TVector);
> > generic procedure ReadVector_From_DM(AFrom: TDataManager; var ASelf:
> > specialize TVector);
> >
> > and use them like this:
> >
> > specialize WriteVector_To_DM(...);
>
> Aha, great, didn't know we had something in this direction. But
> correct me if I am wrong, but this wouldn't work in my case, because
> my function writes the class to a stream in the end of it, so it needs
> to know which type T is. If the type is TSomeClass or a descendent,
> then it will write each field of the class to the stream.
>
> But in a generic class/function there is no way to ask if T is an int,
> or is an TSomeClass, or am I missing some way of writing code that is
> different for various possible types?

You can enforce that T needs to be a subclass of TSomeClass by declaring it
as "T: TSomeClass"; like this:

generic procedure WriteVector_To_DM(ADest: TDataManager;
ASelf: specialize TVector);

In that case the compiler knows that T will at least be a TSomeClass so you
can use methods and fields of it without problems.

Note: these generic constraints also work for generic types and is already
in 3.0.0 for them.

Additionally you can play around with TypeInfo() which works on variables
of a generic type as well.

Regards,
Sven
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Re: [fpc-pascal] Compatibility of very similar generic types

2016-08-18 Thread Felipe Monteiro de Carvalho
On Thu, Aug 18, 2016 at 2:44 PM, Sven Barth  wrote:
> generic procedure WriteVector_To_DM(ADest: TDataManager; ASelf:
> specialize TVector);
> generic procedure ReadVector_From_DM(AFrom: TDataManager; var ASelf:
> specialize TVector);
>
> and use them like this:
>
> specialize WriteVector_To_DM(...);

Aha, great, didn't know we had something in this direction. But
correct me if I am wrong, but this wouldn't work in my case, because
my function writes the class to a stream in the end of it, so it needs
to know which type T is. If the type is TSomeClass or a descendent,
then it will write each field of the class to the stream.

But in a generic class/function there is no way to ask if T is an int,
or is an TSomeClass, or am I missing some way of writing code that is
different for various possible types?

thanks,
-- 
Felipe Monteiro de Carvalho
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Compatibility of very similar generic types

2016-08-18 Thread Sven Barth
Am 18.08.2016 10:57 schrieb "Felipe Monteiro de Carvalho" <
felipemonteiro.carva...@gmail.com>:
>
> Hello,
>
> Consider this:
>
> TSubClass1 = class(TSomeClass)...;
> TSubClass2 = class(TSomeClass)...;
>
> TSubClass1Vector = specialize TVector;
> TSubClass2Vector = specialize TVector;
> TSomeClassVector = specialize TVector;
>
> And I want to write a function like:
>
> procedure WriteVector_To_DM(ADest: TDataManager; ASelf: TSomeClassVector);
> procedure ReadVector_From_DM(AFrom: TDataManager; var ASelf:
TSomeClassVector);

[snip]
>
> Now I understand that some people will scream: DON'T DO THIS.
>
> But my question is: Is there any real reason why I am wrong and will
> fail in some future compiler version or something, or while not
> recommended I am correct that there is no real reason why it could
> possibly fail. Considering my points above?

What you're looking for is a form of type coercion that we don't support
(at least currently; dont know what the future will bring).
Also your assumption is only correct as it is now, however it could be in
the future that the compiler might generate different code for the
different classes, cause of different optimization potential (unlikely, but
I hope you get my point), thus you are relying on implementation details
and thus it will be your own fault if things should stop working in the
future.
One of the cleaner solutions (aside from possible type coercion) is
available on trunk: generic function.
Declare your functions like this:

generic procedure WriteVector_To_DM(ADest: TDataManager; ASelf:
specialize TVector);
generic procedure ReadVector_From_DM(AFrom: TDataManager; var ASelf:
specialize TVector);

and use them like this:

specialize WriteVector_To_DM(...);

Regards,
Sven
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

[fpc-pascal] Compatibility of very similar generic types

2016-08-18 Thread Felipe Monteiro de Carvalho
Hello,

Consider this:

TSubClass1 = class(TSomeClass)...;
TSubClass2 = class(TSomeClass)...;

TSubClass1Vector = specialize TVector;
TSubClass2Vector = specialize TVector;
TSomeClassVector = specialize TVector;

And I want to write a function like:

procedure WriteVector_To_DM(ADest: TDataManager; ASelf: TSomeClassVector);
procedure ReadVector_From_DM(AFrom: TDataManager; var ASelf: TSomeClassVector);

So according to the compiler warnings this is impossible, and I need
to write 3 functions to cover the 3 specializations, even if those
functions would be identical. Which sucks, because in the real case I
have like 10 nearly identical specializations, then I need 10
identical copy+pasted functions... of course I could use
TSomeClassVector everywhere, but this negates the advantages of using
generics in the first place which was type safety and elegancy.

Of course I am not satisfied to copy+paste 10 times and maintain the
copy+pasted mirrors in every change, so I simply wrote only 1 function
for the base class and I call it like this:

var
  myobj: TSubClass1Vector;
begin
  
  ReadVector_From_DM(MyDM, TSomeClassVector(myobj));

Yes, I could write the read/write functions in the vector itself, but
then the vector would need to know about TDataManager, which it is not
supposed to know really :(

The rationale here is that I only use functions from TSubClass1 that
are in TSomeClass, and I can't see how it could go wrong,

I understand that the compiler will generate 3 copies of the same
code: 1 time for TSubClass1Vector, 1 time for TSubClass2Vector and
another for TSomeClassVector. But all those copies should be fully
compatible, considering that:

A> The generic class cannot use anything specific from TSubClass1
since it doesn't know even that we are talking about a class, it could
be an int
B> All classes are equal sized pointers

My conclusion is that doing what I am doing will work, and it can't
possibly fail.

Now I understand that some people will scream: DON'T DO THIS.

But my question is: Is there any real reason why I am wrong and will
fail in some future compiler version or something, or while not
recommended I am correct that there is no real reason why it could
possibly fail. Considering my points above?

thanks,
-- 
Felipe Monteiro de Carvalho
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal