<br />That seriously improves generic code readability. Definitely worth trying to upgrade. Thanks a lot! 20:15, 20 апреля 2022 г., "Sven Barth via fpc-pascal" <fpc-pascal@lists.freepascal.org>:<br /><blockquote class="210e7a848e8fcb45wmi-quote"><p>Dear FPC community,<br /><br />The FPC developers are pleased to announce the implementation of a new <br />feature: implicit generic function specializations. This feature was <br />implemented by Ryan Joseph, so thank you very much, Ryan.<br /><br />This feature allows you to use generic routines (functions, procedures, <br />methods) without explicitely specializing them (“<…>” in Delphi modes <br />and “specialize …<…>” in non-Delphi modes) as long as the compiler can <br />determine the correct parameter types for the generic.<br /><br />This feature is enabled with the modeswitch <br />ImplicitFunctionSpecialization and is for now not enabled by default as <br />this has the potential to break existing code.<br /><br />Assume you have the following function:<br /><br />=== code begin ===<br /><br />generic function Add<T>(aArg1, aArg2: T): T;<br />begin<br />   Result := aArg1 + aArg2;<br />end;<br /><br />=== code end ===<br /><br />Up to now you could only use this function as follows:<br /><br />=== code begin ===<br /><br />SomeStr := specialize Add<String>('Hello', 'World');<br />SomeInt := specialize Add<LongInt>(2, 5);<br /><br />=== code end ===<br /><br />However with implicit function specializations enabled you can also use <br />it as follows:<br /><br />=== code begin ===<br /><br />SomeStr := Add('Hello', 'World');<br />SomeInt := Add(2, 5);<br /><br />=== code end ===<br /><br />The compiler will automatically determine the type of the generic <br />parameters based on the parameters you pass in (this is always done left <br />to right). Depending on the passed in parameters (especially if you're <br />using constant values like in the example instead of variables) the <br />compiler might however pick a different type than you expected. You can <br />enforce a specific type by either explicitely specializing the method as <br />before or by inserting a type cast. In the example above the compile <br />will specialize the call with the parameters “2, 5” using an 8-bit <br />signed type (Pascal prefers signed types) instead of a LongInt as in the <br />explicit specialization. If you use “LongInt(2), 5” as parameters then <br />the compiler will pick that instead, however with “2, LongInt(5)” it <br />will still pick an 8-bit type, because the parameter types are <br />determined left to right.<br /><br />If there exists a non-generic overload for which the parameters types <br />match exactly, the compiler will pick that instead of specializing <br />something anew. So assume you also have the following function in scope:<br /><br />=== code begin ===<br /><br />function Add(aArg1, aArg2: LongInt): LongInt;<br />begin<br />   Result := aArg1 + aArg2;<br />end;<br /><br />=== code end ===<br /><br />In the case of “Add(2, 5)” the compiler will *not* pick the non-generic <br />function, because it determines that an 8-bit type is enough, however if <br />you use “Add(LongInt(2), 5)” the compiler will pick the non-generic <br />function.<br /><br />Aside from simple parameters the compiler also supports arrays and <br />function/method variables:<br /><br />=== code begin ===<br /><br />generic function ArrayFunc<T>(aArg: specialize TArray<T>): T;<br />var<br />   e: T;<br />begin<br />   Result := Default(T);<br />   for e in aArg do<br />     Result := Result + e;<br />end;<br /><br />type<br />   generic TTest<T> = function(aArg: T): T;<br /><br />generic function Apply<T>(aFunc: specialize TTest<T>; aArg: T): T;<br />begin<br />   Result := aFunc(aArg);<br />end;<br /><br />function StrFunc(aArg: String): String;<br />begin<br />   Result := UpCase(aArg);<br />end;<br /><br />function NegFunc(aArg: LongInt): LongInt;<br />begin<br />   Result := - aArg;<br />end;<br /><br />begin<br />   Writeln(ArrayFunc([1, 2, 3])); // will write 6<br />   Writeln(ArrayFunc(['Hello', 'FPC', 'World'])); // will write <br />HelloFPCWorld<br /><br />   <a href="mailto:Writeln(Apply(@StrFunc">Writeln(Apply(@StrFunc</a>, 'Foobar')); // will write FOOBAR<br />   <a href="mailto:Writeln(Apply(@NegFunc">Writeln(Apply(@NegFunc</a>, 42)); // will write -42<br />end.<br /><br />=== code end ===<br /><br />There are of course a few restrictions for this feature:<br />- all generic parameters must be used in the declaration of the routine <br />(implementation only type parameters are not allowed)<br />- all parameters that have a generic type must not be default <br />parameters, they need to be used in the call or their type must have <br />been fixed by a parameter further left (as currently default values for <br />parameters of a generic type are not supported this is not much of a <br />restriction, but should that change (e.g. Default(T)) then this <br />restriction will apply)<br />- the generic routine must not have constant generic parameters (this <br />might be extended in the future with e.g. static arrays or file types, <br />but for now this restriction stands)<br />- the result type is not taken into account, so if only the result type <br />of a routine is generic then an implicit specialization does not work either<br />- function/method pointers to implicit specializations are not yet <br />supported (pointers to explicit specializations are not yet supported <br />either; once this changes the former will change as well)<br />- the compiler will silently discard generic functions that it can't <br />specialize the *declaration* of; however if the declaration can be <br />specialized correctly, but for whatever reason the *implementation* can <br />not then this will trigger a compilation error<br /><br />This feature is by and in itself Delphi compatible however there might <br />be differences in what FPC can implicitely specialize and what Delphi <br />can. Especially if Delphi can specialize something that FPC can not, <br />this should be reported.<br /><br />With kind regards,<br />Sven/Sarah Barth<br />_______________________________________________<br />fpc-pascal maillist  -  <a href="mailto:fpc-pascal@lists.freepascal.org">fpc-pascal@lists.freepascal.org</a><br /><a href="https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal">https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal</a><br /></p></blockquote><br /><br />-- <br />Отправлено из мобильного приложения Яндекс Почты