<div dir="auto"><div><div class="gmail_quote"><div dir="ltr" class="gmail_attr">Ben Grasset via fpc-pascal <<a href="mailto:fpc-pascal@lists.freepascal.org">fpc-pascal@lists.freepascal.org</a>> schrieb am Di., 5. Nov. 2019, 19:11:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div dir="ltr">On Sat, Nov 2, 2019 at 11:51 AM Ryan Joseph via fpc-pascal <<a href="mailto:fpc-pascal@lists.freepascal.org" target="_blank" rel="noreferrer">fpc-pascal@lists.freepascal.org</a>> wrote:<br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Are there any solutions for this currently? I feel like generics need to support some compiler directives so different blocks of code can specialize different depending on the type.<br></blockquote><div><br></div><div>There's one, that works *exactly* like you want (although it's not currently present in trunk FPC) which is to apply the (still-working) patch Sven posted in this mailing list thread a few years ago:</div><div><a href="https://www.mail-archive.com/fpc-pascal@lists.freepascal.org/msg41336.html" target="_blank" rel="noreferrer">https://www.mail-archive.com/fpc-pascal@lists.freepascal.org/msg41336.html</a></div><div><br></div><div>It introduces a const-evaluated "ternary if" of the form "Variable := if Expression else Expression;" where only the true branch is taken into consideration by the compiler at all.</div><div><br></div><div>Combining it with handy compiler intrinsics like GetTypeKind makes stuff like the following modified version of your code possible: <br></div><div><br></div><div>{$mode objfpc}<br>{$modeswitch advancedrecords}<br><br>program generic_vector_2;<br><br>type<br> generic TVec2<TScalar> = record<br> X, Y: TScalar;<br> class function Create(const AX, AY: TScalar): TVec2; static; inline;<br> class operator / (const Left, Right: TVec2): TVec2; inline;<br> end;<br><br> class function TVec2.Create(const AX, AY: TScalar): TVec2;<br> begin<br> with Result do begin<br> X := AX;<br> Y := AY;<br> end;<br> end;<br><br> class operator TVec2./(const Left, Right: TVec2): TVec2;<br> begin<br> // GetTypeKind is evaluated at compile time, so the following works perfectly with "ternary if".<br> Result :=<br> if GetTypeKind(TScalar) = tkFloat then<br> TVec2.Create(Left.X / Right.X, Left.Y / Right.Y)<br> else<br> TVec2.Create(Left.X div Right.X, Left.Y div Right.Y);<br> end;<br><br>type<br> TVec2f = specialize TVec2<Single>;<br> TVec2i = specialize TVec2<Integer>;<br><br>begin<br>end.</div></div></div></blockquote></div></div><div dir="auto"><br></div><div dir="auto">Does this really work? Cause the compiler should nevertheless typecheck the code in the other branch and thus without casts that shouldn't compile. </div><div dir="auto">Also if it should indeed work, it would also work without the if-expression, but with an if-statement. </div><div dir="auto"><br></div><div dir="auto">Regards, </div><div dir="auto">Sven </div><div dir="auto"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
</blockquote></div></div></div>