<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body smarttemplateinserted="true">
    <div id="smartTemplate4-template">Hi Sven,<br>
      <br>
      <p>
        <blockquote type="cite"><br>
          It's not that simple. In principle you're right that the
          compiler could try to merge more implementations, but this
          does not depend on the declaration of the generic, but the use
          of the parameter types.<br>
        </blockquote>
      </p>
      <p>I mostly use generics for containers, especially hashmaps. They
        only stores the values and never calls specific methods on them<br>
         </p>
      <blockquote type="cite"><br>
        <br>
        Not to mention that your TBaseHashMap would not work with
        managed types...</blockquote>
    </div>
    <div><br>
    </div>
    <div>That would need be handled separately. There are probably also
      people who want a container that calls .free on TObject
      descendants.<br>
      <br>
      <br>
      Best,<br>
      Benito </div>
    <div class="moz-cite-prefix">On 26.04.20 14:18, Sven Barth wrote:<br>
    </div>
    <blockquote type="cite"
      cite="mid:42fa7a8a-ace7-4487-848b-bcd31c2e6167@googlemail.com">
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      <div class="moz-cite-prefix">Am 26.04.2020 um 14:01 schrieb Benito
        van der Zander:<br>
      </div>
      <blockquote type="cite"
        cite="mid:01b0729e-bc34-30e7-32e5-c13e32ef1f83@benibela.de">
        <meta http-equiv="Content-Type" content="text/html;
          charset=UTF-8">
        <div id="smartTemplate4-template">Hi,<br>
          <br>
          <p>perhaps it could be used to merge specializations (if fpc
            cannot do that on its own):<br>
          </p>
        </div>
        <div>Like when you have a hashmap THashMap<Key,Value>, and
          need three specializations:</div>
        <div><br>
        </div>
        <div>THashMap<string, pointer></div>
        <div><br>
        </div>
        <div>THashMap<string, TObject></div>
        <div><br>
        </div>
        <div>THashMap<string, sizeint></div>
        <div><br>
        </div>
        <div>It is basically three times the same hashmap, but if fpc
          does not detect that, it might generate three times the same
          assembly code, which waste a lot of space.</div>
        <div><br>
        </div>
        <div><br>
        </div>
        <div>But with constants it can be merged to TBaseHashMap<Key,
          ValueSize: integer> and then you only have one map in the
          assembly code, and three wrappers to remove the casting:<br>
        </div>
        <div><br>
        </div>
        <div>
          <div>THashMap<string, pointer> = TBaseHashMap<string,
            sizeof(pointer) > = TBaseHashMap<string, 8 >  </div>
          <div><br>
          </div>
          <div>THashMap<string, TObject> = TBaseHashMap<string,
            sizeof(TObject) > = TBaseHashMap<string, 8 > <br>
          </div>
          <div><br>
          </div>
          <div>THashMap<string, sizeint> = TBaseHashMap<string,
            sizeof(sizeint) > = TBaseHashMap<string, 8 > <br>
          </div>
          <div><br>
          </div>
        </div>
      </blockquote>
      <br>
      It's not that simple. In principle you're right that the compiler
      could try to merge more implementations, but this does not depend
      on the declaration of the generic, but the use of the parameter
      types.<br>
      <br>
      Take the following example:<br>
      <br>
      === code begin ===<br>
      <br>
      {$mode objfpc}<br>
      <br>
      type<br>
        generic TTest<T> = class<br>
          procedure DoSomething;<br>
        end;<br>
      <br>
        TMyClass1 = class<br>
           procedure Foobar;<br>
        end;<br>
      <br>
        TMyClass2 = class<br>
          procedure Foobar; virtual;<br>
        end;<br>
      <br>
      procedure TTest.DoSomething;<br>
      var<br>
        o: T;<br>
      begin<br>
        o.Foobar;<br>
      end;<br>
      <br>
      procedure TMyClass1.Foobar;<br>
      begin<br>
        Writeln('TMyClass1.Foobar');<br>
      end;<br>
      <br>
      procedure TMyClass2.Foobar;<br>
      begin<br>
        Writeln('TMyClass2.Foobar');<br>
      end;<br>
      <br>
      type<br>
        TTestMyClass1 = specialize TTest<TMyClass1>;<br>
        TTestMyClass2 = specialize TTest<TMyClass2>;<br>
      <br>
      begin<br>
      end.<br>
      <br>
      === code end ===<br>
      <br>
      In case of TMyClass1 this will result in a static call to
      TMyClass1.Foobar, however in case of TMyClass2 this will result in
      an indirect call through the VMT.<br>
      <br>
      The type information needs to be correct as well, even more so
      once we have support for Extended RTTI where one can enumerate
      non-published fields, properties and methods in addition to
      published. <br>
      <br>
      Not to mention that your TBaseHashMap would not work with managed
      types...<br>
      <br>
      Regards,<br>
      Sven<br>
    </blockquote>
  </body>
</html>