<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>
<channel>
	<title>Comments on: Comparing C#, C++, and Delphi (Win32) Generics</title>
	<atom:link href="http://blogs.teamb.com/craigstuntz/2009/10/01/38465/feed/" rel="self" type="application/rss+xml" />
	<link>http://blogs.teamb.com/craigstuntz/2009/10/01/38465/</link>
	<description>C# • Entity Framework • Functional Programming • MVC • Web</description>
	<pubDate>Sun, 12 Feb 2012 05:01:14 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.2</generator>
		<item>
		<title>By: 30km</title>
		<link>http://blogs.teamb.com/craigstuntz/2009/10/01/38465/#comment-11742</link>
		<dc:creator>30km</dc:creator>
		<pubDate>Mon, 16 Nov 2009 23:18:20 +0000</pubDate>
		<guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38465#comment-11742</guid>
		<description>Very helpful resource for me to get started with Delphi generics. It is very different from C++ templates, and sometimes seems buggy:P</description>
		<content:encoded><![CDATA[<p>Very helpful resource for me to get started with Delphi generics. It is very different from C++ templates, and sometimes seems buggy:P</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: John Moshakis</title>
		<link>http://blogs.teamb.com/craigstuntz/2009/10/01/38465/#comment-9952</link>
		<dc:creator>John Moshakis</dc:creator>
		<pubDate>Fri, 02 Oct 2009 16:31:03 +0000</pubDate>
		<guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38465#comment-9952</guid>
		<description>Delphi Prism has had covariance and contravariance for a while, this is the wiki page

http://prismwiki.codegear.com/en/Generic_Variance</description>
		<content:encoded><![CDATA[<p>Delphi Prism has had covariance and contravariance for a while, this is the wiki page</p>
<p><a href="http://prismwiki.codegear.com/en/Generic_Variance" rel="nofollow">http://prismwiki.codegear.com/en/Generic_Variance</a></p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Moritz Beutel</title>
		<link>http://blogs.teamb.com/craigstuntz/2009/10/01/38465/#comment-9937</link>
		<dc:creator>Moritz Beutel</dc:creator>
		<pubDate>Thu, 01 Oct 2009 20:32:33 +0000</pubDate>
		<guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38465#comment-9937</guid>
		<description>Great summary, thanks.

On the C++ part, I think it should be noted that, while most compilers simply reparse the substituted template definition when instantiating it, the standard actually demands "two-phase name lookup", which requires that the template be parsed as far as possible, and all expressions which don't depend on the template arguments be checked syntactically and semantically when the template definition is first encountered. I think only EDG's frontend (which is being used for Intel's and Comeau's C++ compiler) implements this correctly.

I understand that you're concentrating on the technical implementation bits, but especially when mentioning concepts, I think that one major flaw of C++ templates is worth mentioning: constraint errors being reported as errors in the actual template. This was one of the major issues which Concepts were meant to address. As an example, imagine calling the std::sort algorithm, which requires you to pass random-access iterators:

&lt;blockquote&gt;&lt;code&gt;// -----
  std::vector &#60;int&#62; myInts (42);
  std::sort (myInts.begin (), myInts.end (), std::less &#60;int&#62; ());
// -----&lt;/code&gt;&lt;/blockquote&gt;

This works fine - the code instantiates a vector of ints, sets the size to 42 and then sorts them; to access a specific element in the array, it uses direct index access via the first iterator, i.e. myints.begin()[n]. Now, the cool things about iterators is that their handling is independent from the type of the container they belong to, similar to IComparable/IEnumerable, but with all the polymorphism being resolved at compile time. So for most algorithms that only require uni- or bidirectional iterators, changing the std::vector to a std::list would just work fine. But as I said, std::sort() requires random access iterators (which provide an overload for the [] operator), so calling std::sort() with iterators pointing to a linked list will fail. Of course the error is in the user's code: calling std::sort() on iterators without random access isn't supposed to work. But the sad thing is that the compiler won't tell you: e.g., all you get from BCC is two errors in system headers (sorry for German language):

&lt;blockquote&gt;// -----
Fehler E2093 E:\Programme\Weaver\\Include\dinkumware\algorithm 2220: 'operator-' ist im Typ 'list&#60;int,allocator &#62;::iterator' für Argumente desselben Typs nicht implementiert in Funktion std::void sort&#60;list&#60;int,allocator &#62;::iterator,less &#62;(list&#60;int,allocator &#62;::iterator,list&#60;int,allocator &#62;::iterator,less)
Fehler E2285 E:\Programme\Weaver\\Include\dinkumware\algorithm 2220: Keine Übereinstimmung für '_Sort(list&#60;int,allocator &#62;::iterator,list&#60;int,allocator &#62;::iterator,undefined,less)' gefunden in Funktion void sort&#60;list&#60;int,allocator &#62;::iterator,less &#62;(list&#60;int,allocator &#62;::iterator,list&#60;int,allocator &#62;::iterator,less)
// -----&lt;/blockquote&gt;

This is because std::sort() is a function template, and as such it's just reparsed for this instantiation, but with above type substitution, the reparse causes an error - which of course occurs in the actual template code. Note that BCC is one of the well-behaving compilers WRT template error messages - with a little experience, you can see what happened in above messages, and with Extended Error Info turned on the compiler will even tell you about the file which the instantiation occurred in. But not all compilers are that easy to work with. Just look at the output EDG generates for this code (you can try it online on Dinkumware's site at http://www.dinkumware.com/exam/default.aspx):

&lt;blockquote&gt;&lt;code&gt;// -----
#include &#60;algorithm&#62;
#include &#60;vector&#62;
#include &#60;list&#62;

int main (void)
{
  //std::vector &#60;int&#62; myInts (42);
  std::list &#60;int&#62; myInts;
  std::sort (myInts.begin (), myInts.end (), std::less &#60;int&#62; ());
}
// -----&lt;/code&gt;&lt;/blockquote&gt;

I won't quote the output here, for it's 37 error messages spread over a total of 863 lines, all of which point to the system header std::sort() is defined in.

Also, while reading the bit on covariance and contravariance, though, I thought you should have mentioned Java there. While I think that Java's generics are fundamentally crippled due to their use of type erasure (for the sake of JVM backward compatibility), they still handle covariance and contravariance nicely, something which I often miss in C++ and Delphi.


&lt;blockquote&gt;&lt;i&gt;&lt;b&gt;Response:&lt;/b&gt; Thank you very much, Moritz, this is a great comment! I've taken the liberty of formatting your source code and replacing the angle brackets; please let me know if I've missed anything. Great point about the error messages; I will update the article to include that (with the clarification in your second paragraph). I really appreciate all the thought you put into the comment! Regarding Java, I didn't include it because, unlike the other languages which I did include, I consider the implementation to be essentially broken by design (for precisely the reason you mention). It would've been very interesting to include Scala, but I would need to understand it better to say anything intelligent on the subject.&lt;/i&gt;&lt;/blockquote&gt;</description>
		<content:encoded><![CDATA[<p>Great summary, thanks.</p>
<p>On the C++ part, I think it should be noted that, while most compilers simply reparse the substituted template definition when instantiating it, the standard actually demands "two-phase name lookup", which requires that the template be parsed as far as possible, and all expressions which don&#8217;t depend on the template arguments be checked syntactically and semantically when the template definition is first encountered. I think only EDG&#8217;s frontend (which is being used for Intel&#8217;s and Comeau&#8217;s C++ compiler) implements this correctly.</p>
<p>I understand that you&#8217;re concentrating on the technical implementation bits, but especially when mentioning concepts, I think that one major flaw of C++ templates is worth mentioning: constraint errors being reported as errors in the actual template. This was one of the major issues which Concepts were meant to address. As an example, imagine calling the std::sort algorithm, which requires you to pass random-access iterators:</p>
<blockquote><p><code>// -----<br />
  std::vector &lt;int&gt; myInts (42);<br />
  std::sort (myInts.begin (), myInts.end (), std::less &lt;int&gt; ());<br />
// -----</code></p></blockquote>
<p>This works fine - the code instantiates a vector of ints, sets the size to 42 and then sorts them; to access a specific element in the array, it uses direct index access via the first iterator, i.e. myints.begin()[n]. Now, the cool things about iterators is that their handling is independent from the type of the container they belong to, similar to IComparable/IEnumerable, but with all the polymorphism being resolved at compile time. So for most algorithms that only require uni- or bidirectional iterators, changing the std::vector to a std::list would just work fine. But as I said, std::sort() requires random access iterators (which provide an overload for the [] operator), so calling std::sort() with iterators pointing to a linked list will fail. Of course the error is in the user&#8217;s code: calling std::sort() on iterators without random access isn&#8217;t supposed to work. But the sad thing is that the compiler won&#8217;t tell you: e.g., all you get from BCC is two errors in system headers (sorry for German language):</p>
<blockquote><p>// &#8212;&#8211;<br />
Fehler E2093 E:\Programme\Weaver\\Include\dinkumware\algorithm 2220: &#8216;operator-&#8217; ist im Typ &#8216;list&lt;int,allocator &gt;::iterator&#8217; für Argumente desselben Typs nicht implementiert in Funktion std::void sort&lt;list&lt;int,allocator &gt;::iterator,less &gt;(list&lt;int,allocator &gt;::iterator,list&lt;int,allocator &gt;::iterator,less)<br />
Fehler E2285 E:\Programme\Weaver\\Include\dinkumware\algorithm 2220: Keine Übereinstimmung für &#8216;_Sort(list&lt;int,allocator &gt;::iterator,list&lt;int,allocator &gt;::iterator,undefined,less)&#8217; gefunden in Funktion void sort&lt;list&lt;int,allocator &gt;::iterator,less &gt;(list&lt;int,allocator &gt;::iterator,list&lt;int,allocator &gt;::iterator,less)<br />
// &#8212;&#8211;</p></blockquote>
<p>This is because std::sort() is a function template, and as such it&#8217;s just reparsed for this instantiation, but with above type substitution, the reparse causes an error - which of course occurs in the actual template code. Note that BCC is one of the well-behaving compilers WRT template error messages - with a little experience, you can see what happened in above messages, and with Extended Error Info turned on the compiler will even tell you about the file which the instantiation occurred in. But not all compilers are that easy to work with. Just look at the output EDG generates for this code (you can try it online on Dinkumware&#8217;s site at <a href="http://www.dinkumware.com/exam/default.aspx" rel="nofollow">http://www.dinkumware.com/exam/default.aspx</a>):</p>
<blockquote><p><code>// -----<br />
#include &lt;algorithm&gt;<br />
#include &lt;vector&gt;<br />
#include &lt;list&gt;</p>
<p>int main (void)<br />
{<br />
  //std::vector &lt;int&gt; myInts (42);<br />
  std::list &lt;int&gt; myInts;<br />
  std::sort (myInts.begin (), myInts.end (), std::less &lt;int&gt; ());<br />
}<br />
// -----</code></p></blockquote>
<p>I won&#8217;t quote the output here, for it&#8217;s 37 error messages spread over a total of 863 lines, all of which point to the system header std::sort() is defined in.</p>
<p>Also, while reading the bit on covariance and contravariance, though, I thought you should have mentioned Java there. While I think that Java&#8217;s generics are fundamentally crippled due to their use of type erasure (for the sake of JVM backward compatibility), they still handle covariance and contravariance nicely, something which I often miss in C++ and Delphi.</p>
<blockquote><p><i><b>Response:</b> Thank you very much, Moritz, this is a great comment! I&#8217;ve taken the liberty of formatting your source code and replacing the angle brackets; please let me know if I&#8217;ve missed anything. Great point about the error messages; I will update the article to include that (with the clarification in your second paragraph). I really appreciate all the thought you put into the comment! Regarding Java, I didn&#8217;t include it because, unlike the other languages which I did include, I consider the implementation to be essentially broken by design (for precisely the reason you mention). It would&#8217;ve been very interesting to include Scala, but I would need to understand it better to say anything intelligent on the subject.</i></p></blockquote>
]]></content:encoded>
	</item>
	<item>
		<title>By: Jolyon Smith</title>
		<link>http://blogs.teamb.com/craigstuntz/2009/10/01/38465/#comment-9936</link>
		<dc:creator>Jolyon Smith</dc:creator>
		<pubDate>Thu, 01 Oct 2009 19:30:21 +0000</pubDate>
		<guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38465#comment-9936</guid>
		<description>"so developers will benefit from the feature without having to fully understand it"

A path paved with folly and edged with razors on one side and a precipitous cliff on the other, imho and ime.  ymmv.  :)

&lt;blockquote&gt;&lt;i&gt;&lt;b&gt;Response:&lt;/b&gt; I view it as very much like ASM. My wild guess is that the majority of Delphi developers don't understand ASM. Yet all Delphi developers use routines written in ASM, every day, and in every program they write. Will you be a better Delphi developer if you do understand ASM? Yes, certainly; even if you never write in ASM routine yourself, you will regularly debug through them. But can you get started and be a productive developer without learning ASM first? The evidence I've seen suggests yes.&lt;/i&gt;&lt;/blockquote&gt;</description>
		<content:encoded><![CDATA[<p>"so developers will benefit from the feature without having to fully understand it"</p>
<p>A path paved with folly and edged with razors on one side and a precipitous cliff on the other, imho and ime.  ymmv.  <img src='http://blogs.teamb.com/craigstuntz/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<blockquote><p><i><b>Response:</b> I view it as very much like ASM. My wild guess is that the majority of Delphi developers don&#8217;t understand ASM. Yet all Delphi developers use routines written in ASM, every day, and in every program they write. Will you be a better Delphi developer if you do understand ASM? Yes, certainly; even if you never write in ASM routine yourself, you will regularly debug through them. But can you get started and be a productive developer without learning ASM first? The evidence I&#8217;ve seen suggests yes.</i></p></blockquote>
]]></content:encoded>
	</item>
</channel>
</rss>

