<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Fehler im C++ International Standard?]]></title><description><![CDATA[<p>So nun nach mehr als einer Woche habe FAST (aktuell bis Tipp 45), Effektiv C++ Programmieren von Scott Meyers durch, in diesem Zusammenhang habe ich eine Frage bezüglich der Funktions-Templates und deren Überladung, Spezifizierung und ODR.</p>
<p>Beispiel <strong>S.298</strong> aus <strong>n1905</strong> (dem <strong>C++ International Standard</strong>):</p>
<pre><code class="language-cpp">template &lt; typename T &gt;
void f ( T *) {};

void g ( int * p )
{
    f ( p ); // call
             // f&lt;int&gt;(int*)
}

template &lt; typename T &gt;
void f ( T ) {};

void h ( int * p ) {
    f ( p ); // call
             // f&lt;int*&gt;(int*) &lt;-- was ?????
}

int main()
{
    int xy = 1;
    g(&amp;xy);
    h(&amp;xy);
}
</code></pre>
<p>Das oben gezeigte Beispiel kann meines Erachtens nicht richtig, bzw. richtig kommentiert sein. Als typename kommen nur Typen in Frage also</p>
<pre><code class="language-cpp">template&lt; typename T &gt; void foo() {}; // Ok Typ void foo&lt;T&gt;()
template&lt; typename T* &gt; void foo() {}; // Sollte nicht funktionieren -&gt;  foo&lt;T*&gt;()
</code></pre>
<p>Ich habe das Beipiel als Erklärung aus dem Kapitel <strong>14.5.5.1 Function template overloading S.298</strong> so verstanden:</p>
<pre><code class="language-cpp">template &lt; typename T &gt;
void f ( T *) {};

void g ( int * p )
{
    f ( p ); // call
             // f&lt;int&gt;(int*)
}

template &lt; typename T &gt;
void f ( T ) {};

void h ( int * p ) {
    f ( *p ); // call (Dereferenziere)
             // f&lt;int&gt;(int) &lt;- richtig!
}

int main()
{
    int xy = 1;
    g(&amp;xy);
    h(&amp;xy);
}
</code></pre>
<p>Vielleicht verstehe ich aber den Standard falsch?</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/250778/fehler-im-c-international-standard</link><generator>RSS for Node</generator><lastBuildDate>Tue, 15 Sep 2026 19:50:19 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/250778.rss" rel="self" type="application/rss+xml"/><pubDate>Wed, 23 Sep 2009 22:15:28 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Fehler im C++ International Standard? on Wed, 23 Sep 2009 22:48:07 GMT]]></title><description><![CDATA[<p>So nun nach mehr als einer Woche habe FAST (aktuell bis Tipp 45), Effektiv C++ Programmieren von Scott Meyers durch, in diesem Zusammenhang habe ich eine Frage bezüglich der Funktions-Templates und deren Überladung, Spezifizierung und ODR.</p>
<p>Beispiel <strong>S.298</strong> aus <strong>n1905</strong> (dem <strong>C++ International Standard</strong>):</p>
<pre><code class="language-cpp">template &lt; typename T &gt;
void f ( T *) {};

void g ( int * p )
{
    f ( p ); // call
             // f&lt;int&gt;(int*)
}

template &lt; typename T &gt;
void f ( T ) {};

void h ( int * p ) {
    f ( p ); // call
             // f&lt;int*&gt;(int*) &lt;-- was ?????
}

int main()
{
    int xy = 1;
    g(&amp;xy);
    h(&amp;xy);
}
</code></pre>
<p>Das oben gezeigte Beispiel kann meines Erachtens nicht richtig, bzw. richtig kommentiert sein. Als typename kommen nur Typen in Frage also</p>
<pre><code class="language-cpp">template&lt; typename T &gt; void foo() {}; // Ok Typ void foo&lt;T&gt;()
template&lt; typename T* &gt; void foo() {}; // Sollte nicht funktionieren -&gt;  foo&lt;T*&gt;()
</code></pre>
<p>Ich habe das Beipiel als Erklärung aus dem Kapitel <strong>14.5.5.1 Function template overloading S.298</strong> so verstanden:</p>
<pre><code class="language-cpp">template &lt; typename T &gt;
void f ( T *) {};

void g ( int * p )
{
    f ( p ); // call
             // f&lt;int&gt;(int*)
}

template &lt; typename T &gt;
void f ( T ) {};

void h ( int * p ) {
    f ( *p ); // call (Dereferenziere)
             // f&lt;int&gt;(int) &lt;- richtig!
}

int main()
{
    int xy = 1;
    g(&amp;xy);
    h(&amp;xy);
}
</code></pre>
<p>Vielleicht verstehe ich aber den Standard falsch?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1783337</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1783337</guid><dc:creator><![CDATA[DeepCopy]]></dc:creator><pubDate>Wed, 23 Sep 2009 22:48:07 GMT</pubDate></item><item><title><![CDATA[Reply to Fehler im C++ International Standard? on Wed, 23 Sep 2009 22:29:06 GMT]]></title><description><![CDATA[<p>Wieso soll <code>T*</code> nicht funktionieren? <code>T*</code> ist ja ein Typ.</p>
<p>Im Allgemeinen wird bei der Auswahl der Funktion der am meisten spezialisierte Typ ausgesucht, und ein Zeigertyp ist spezialisierter als irgendein Typ. Natürlich gibt es hier ein paar Fallgruben, zum Beispiel bezüglich partieller Templatespezialisierung und Überladung, wo man intuitiv etwas anderes erwarten würde (&quot;natürlich&quot;, weil wir in C++ programmieren :)).</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1783339</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1783339</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Wed, 23 Sep 2009 22:29:06 GMT</pubDate></item><item><title><![CDATA[Reply to Fehler im C++ International Standard? on Wed, 23 Sep 2009 22:47:15 GMT]]></title><description><![CDATA[<p>Auf eine Änderung des Typen von <strong>T</strong> in <strong>T</strong>* im folgenden Code:</p>
<pre><code class="language-cpp">template &lt; typename T* &gt;
void f ( T *) {};

void g ( int * p )
{
    f ( p ); // call
             // f&lt;int&gt;(int*)
}
</code></pre>
<p>reagiert der GCC 4.3.3 sehr ungehalten <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /> :</p>
<pre><code>main.cpp|1|Fehler: expected nested-name-specifier before »T«|
</code></pre>
<p>Mache ich was falsch?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1783344</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1783344</guid><dc:creator><![CDATA[DeepCopy]]></dc:creator><pubDate>Wed, 23 Sep 2009 22:47:15 GMT</pubDate></item><item><title><![CDATA[Reply to Fehler im C++ International Standard? on Wed, 23 Sep 2009 23:05:35 GMT]]></title><description><![CDATA[<p>n1905 ist <em>nicht</em> der C++ Standard sondern ein veralteter Entwurf für den nächsten C++ Standard. Zudem sind Kapitel/Absatz-Angaben in der Regel sinnvoller, weil das den Vergleich mit anderen Versionen erleichtert. Im Übrigen sieht das Beispiel völlig anders aus:</p>
<blockquote>
<p>It is possible to overload function templates so that two different function template specializations have the same type.<br />
[ Example:<br />
/ / file1.c<br />
template &lt; class T&gt;<br />
void f(T*);<br />
void g(int * p) {<br />
f(p); / / call<br />
/ / f&lt;int&gt;(int*)<br />
}</p>
<p>/ / file2.c<br />
template &lt; class T&gt;<br />
void f(T);<br />
void h(int * p) {<br />
f(p); / / call<br />
/ / f&lt;int*&gt;(int*)<br />
}<br />
—end example ]<br />
2 Such specializations are distinct functions and do not violate the one definition rule (3.2).</p>
</blockquote>
<p>In diesem Beispiel sind die Überladungen in <em>verschiedenen ÜEs</em> definiert, eine Aussage, welche Spezialiserung bei Argumentdeduktion vorzuziehen wäre, wenn beide gleichzeitig deklariert wurden, wird hier gar nicht gemacht.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1783347</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1783347</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Wed, 23 Sep 2009 23:05:35 GMT</pubDate></item><item><title><![CDATA[Reply to Fehler im C++ International Standard? on Thu, 24 Sep 2009 00:11:23 GMT]]></title><description><![CDATA[<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/6642">@camper</a> - war total richtig was du gesagt hast... ich bin einfach zu blöd <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/26a0.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--warning"
      title=":warning:"
      alt="⚠"
    /></p>
<p>PS.: Ich muss mich noch bei Dir bedanken für die Erklärung zur Orthogonalität, das ich dich immer Zitiert habe war reiner Zufall, nimm's als Kompliment von mir. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f44d.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--thumbs_up"
      title=":+1:"
      alt="👍"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1783351</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1783351</guid><dc:creator><![CDATA[DeepCopy]]></dc:creator><pubDate>Thu, 24 Sep 2009 00:11:23 GMT</pubDate></item><item><title><![CDATA[Reply to Fehler im C++ International Standard? on Thu, 24 Sep 2009 00:22:16 GMT]]></title><description><![CDATA[<p>So, also laut <strong>14.8 Function template specializations</strong> - die haben da meiner Meinung nach einen Fehler gemacht - (IMHO) müsste die nachstehende Funktion eigentlich so arbeiten:</p>
<pre><code class="language-cpp">// file1.cpp
template &lt; typename T &gt;
void f ( T *) {};

void g ( int * p )
{
    f ( p ); // call
             // f&lt;int*&gt;(int**) &lt;-- der Typ ist int* die Funktion übernimmt Argument auf T* = int**
}

// file2.cpp

template &lt; typename T &gt;
void f ( T );

void h ( int * p ) {
    f ( p ); // call
             // f&lt;int*&gt;(int*) &lt;-- der Typ ist int* die Funktion übernimmt ein Argument auf T = int *
}
</code></pre>
<p>Da jede ÜE für sich übersetzt wird muss die entsprechende Funktion (wenn nicht als extern deklariert) bereits zur Compile-Time vorhanden sein. Dh. mein Missverständnis beim zweiten Aufruf, aber was ist dann mit dem ersten Aufruf an void f ( T* ) - der funktioniert doch jetzt nach ganz anderen Regeln...</p>
<p>Oder bin ich total von Rolle <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f615.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--confused_face"
      title=":confused:"
      alt="😕"
    /></p>
<p>Und soweit ich das überblicken kann darf in</p>
<pre><code class="language-cpp">template &lt; typename T &gt;
</code></pre>
<p>nicht anderes angegeben sein als der Typname T ohne '*' und '&amp;'.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1783353</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1783353</guid><dc:creator><![CDATA[DeepCopy]]></dc:creator><pubDate>Thu, 24 Sep 2009 00:22:16 GMT</pubDate></item><item><title><![CDATA[Reply to Fehler im C++ International Standard? on Thu, 24 Sep 2009 00:58:02 GMT]]></title><description><![CDATA[<p>Und hier das Beispiel aus dem C++ International Standard<br />
Kap. <strong>14.8.2</strong> was mich verwirrt hat.</p>
<blockquote>
<pre><code class="language-cpp">template &lt; class T &gt; void f ( T * p )
    {
       static T s ;
       / / ...
    };
    void g ( int a , char * b )
    {
       f (&amp; a ); // call f&lt;int&gt;(int*)
       f (&amp; b ); // call f&lt;char*&gt;(char**)
    }
</code></pre>
<p>Here f&lt;int&gt;(int*) has a static variable s of type int and f&lt;char*&gt;(char**) has a static variable s of type char*.</p>
</blockquote>
<p>Wenn das tatsächlich stimmen sollte das</p>
<pre><code class="language-cpp">f&lt;char*&gt;(char**)
</code></pre>
<p>übergeben wird und</p>
<blockquote>
<p>s vom Typ char*</p>
</blockquote>
<p>ist, wie könnte ich dann in der Funktion neue Stack-Objekte erstellen, etwas so:</p>
<pre><code class="language-cpp">[cpp]template &lt; class T &gt; void f ( T * p )
    {
       static T s ;  // T ist vom Typ char*
       *T o1;        // das geht so nicht, nur zur Demo.
       *T* p1;       // und zurück auf Pointer natürlich so auch nicht, nur zur Demo.
       / / ...
    };
</code></pre>
<p>Da wäre es doch in jedem Fall sinnvoller NUR den zeigerfreien Objekt-Typen zu übergeben, und der der Funktion das zu deklarieren was man Typen tatsächlich braucht.</p>
<pre><code class="language-cpp">template &lt; class T &gt; void f ( T * p )
    {
       static T* s ; // T ist vom Typ  char
       T o1;         // das geht jetzt
       T* p1;        // und das natürlich auch
       / / ...
    };
</code></pre>
<p>Hab ich das Richtig verstanden? <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f615.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--confused_face"
      title=":confused:"
      alt="😕"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1783355</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1783355</guid><dc:creator><![CDATA[DeepCopy]]></dc:creator><pubDate>Thu, 24 Sep 2009 00:58:02 GMT</pubDate></item><item><title><![CDATA[Reply to Fehler im C++ International Standard? on Thu, 24 Sep 2009 03:26:28 GMT]]></title><description><![CDATA[<p>DeepCopy schrieb:</p>
<blockquote>
<pre><code class="language-cpp">// file1.cpp
template &lt; typename T &gt;
void f ( T *) {};

void g ( int * p )
{
    f ( p ); // call
             // f&lt;int*&gt;(int**) &lt;-- der Typ ist int* die Funktion übernimmt Argument auf T* = int**
}
</code></pre>
</blockquote>
<p>T ist hier dein generischer Typ. Dein Parameter ist <strong>T</strong>*, dein Argument <strong>int</strong>*. T wird versucht zu deduzieren. T wird folglich zu int ausgewertet.</p>
<p>DeepCopy schrieb:</p>
<blockquote>
<pre><code class="language-cpp">// file2.cpp

template &lt; typename T &gt;
void f ( T );

void h ( int * p ) {
    f ( p ); // call
             // f&lt;int*&gt;(int*) &lt;-- der Typ ist int* die Funktion übernimmt ein Argument auf T = int *
}
</code></pre>
</blockquote>
<p>Andere ÜE. Kein Bezug zu file1.cpp. T ist hier dein generischer Typ. Dein Parameter ist <strong>T</strong>, dein Argument <strong>int</strong>*. T wird versucht zu deduzieren. T wird folglich zu int* ausgewertet.</p>
<p>DeepCopy schrieb:</p>
<blockquote>
<p>Und soweit ich das überblicken kann darf in</p>
<pre><code class="language-cpp">template &lt; typename T &gt;
</code></pre>
<p>nicht anderes angegeben sein als der Typname T ohne '*' und '&amp;'.</p>
</blockquote>
<p>Yes.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1783363</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1783363</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Thu, 24 Sep 2009 03:26:28 GMT</pubDate></item><item><title><![CDATA[Reply to Fehler im C++ International Standard? on Thu, 24 Sep 2009 03:40:46 GMT]]></title><description><![CDATA[<p>DeepCopy schrieb:</p>
<blockquote>
<p>Wenn das tatsächlich stimmen sollte das</p>
<pre><code class="language-cpp">f&lt;char*&gt;(char**)
</code></pre>
<p>übergeben wird und</p>
<blockquote>
<p>s vom Typ char*</p>
</blockquote>
<p>ist, wie könnte ich dann in der Funktion neue Stack-Objekte erstellen</p>
</blockquote>
<p>In dem Falle hast du nur noch ein T=char* und kannst auf direkten Wege keinen char's erstellen. Trait-Klassen könnten dir bei sowas helfen, siehe boost oder simple:</p>
<pre><code class="language-cpp">template&lt;typename T&gt;
struct PtrToTyp;

template&lt;&gt;
struct PtrToTyp&lt;char*&gt;
{
    typedef char Type;
};

template &lt;class T&gt; 
void f (T * p)
{
   typename PtrToTyp&lt;T&gt;::Type c = 'c';
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1783364</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1783364</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Thu, 24 Sep 2009 03:40:46 GMT</pubDate></item><item><title><![CDATA[Reply to Fehler im C++ International Standard? on Thu, 24 Sep 2009 16:57:21 GMT]]></title><description><![CDATA[<p>@KasF:<br />
Es geht im um die ODR.</p>
<p>Also ob es OK ist, ein Funktions-Template in einer Datei als &quot;void f(T)&quot; und in einer anderen als &quot;void f(T*)&quot; zu definieren.<br />
Templates haben nunmal external linkage, von daher ist die ODR hier sehr relevant.</p>
<p>Ich bin mir ziemlich sicher, dass es NICHT OK ist. Sprich: eine Verletzung der ODR. Ich müsste aber auch erst nachsehen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1783742</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1783742</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Thu, 24 Sep 2009 16:57:21 GMT</pubDate></item><item><title><![CDATA[Reply to Fehler im C++ International Standard? on Fri, 25 Sep 2009 03:28:28 GMT]]></title><description><![CDATA[<p>Ich dachte das wäre schon geklärt.</p>
<p>hustbaer schrieb:</p>
<blockquote>
<p>Also ob es OK ist, ein Funktions-Template in einer Datei als &quot;void f(T)&quot; und in einer anderen als &quot;void f(T*)&quot; zu definieren.</p>
</blockquote>
<p>Wir haben hier einmal f**&lt;int&gt;<strong>(...) und f</strong>&lt;int*&gt;**(...), dies verletzt nicht die ODR.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1783871</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1783871</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Fri, 25 Sep 2009 03:28:28 GMT</pubDate></item><item><title><![CDATA[Reply to Fehler im C++ International Standard? on Fri, 25 Sep 2009 07:54:35 GMT]]></title><description><![CDATA[<p>Also ich meine den Fall, mit einmal f&lt;int&gt;(int*) und einmal f&lt;int&gt;(int).</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1783917</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1783917</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Fri, 25 Sep 2009 07:54:35 GMT</pubDate></item><item><title><![CDATA[Reply to Fehler im C++ International Standard? on Fri, 25 Sep 2009 08:25:55 GMT]]></title><description><![CDATA[<p>hustbaer schrieb:</p>
<blockquote>
<p>Also ich meine den Fall, mit einmal f&lt;int&gt;(int*) und einmal f&lt;int&gt;(int).</p>
</blockquote>
<p>Wieso sollte das problematisch sein? Es geht ja auch f(int) und f(int*) wenn wir es mit normalen Funktionen zu tun haben.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1783945</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1783945</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Fri, 25 Sep 2009 08:25:55 GMT</pubDate></item><item><title><![CDATA[Reply to Fehler im C++ International Standard? on Fri, 25 Sep 2009 09:19:57 GMT]]></title><description><![CDATA[<p>Aua, ja, danke.</p>
<p>Meiner Vermutung liegt eine ziemlich peinliche Wissenslücke bezüglich Spezialisierung von Funktions-Templates zu Grunde...</p>
<p>Die ich aber hier nicht weiter erklären will <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1783987</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1783987</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Fri, 25 Sep 2009 09:19:57 GMT</pubDate></item><item><title><![CDATA[Reply to Fehler im C++ International Standard? on Sat, 26 Sep 2009 22:34:37 GMT]]></title><description><![CDATA[<p>Also wenn ich das richtig verstanden habe ist die Deduktion von generischen Typen mit dem Kürzen von Brüchen vergleichbar, wenn ich als Argument int* und Parameter T*, dann kann ich den '<em>' bei beiden &quot;Rauskürzen&quot;, wenn ich als Argument int und Parameter T</em> kann ich nichts &quot;Rauskürzen&quot; also bleibt int* übrig, also kurz: Immer der &quot;meist spezialisierte Typ&quot; nach dem &quot;Kürzen&quot; ist anzuwenden.</p>
<p>Die Deduktion scheint immer angewandt zu werden, egal ob das mit den Funktionssignaturen nachher kompatibel ist oder nicht, d.h. wenn ich ein int übergebe und mein Parameter will T*, wird sich der Compiler nach der Deduktion beschweren.</p>
<p>So weit, so gut. Aber: was ist wenn als Argument int&amp; und Parameter T* gefordert sind, oder auch anderes herum, wenn int* als Argument und Parameter T&amp; gefordert werden? Hier kann ich nicht &quot;Kürzen&quot; da einmal eine Referenz und einmal ein Zeiger vorhanden ist, was ist das Ergebnis der Deduktion? Bleibt &quot;int*&quot; oder &quot;int&amp;&quot;, darf hier die Spezialisierung angewendet werden?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1784771</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1784771</guid><dc:creator><![CDATA[DeepCopy]]></dc:creator><pubDate>Sat, 26 Sep 2009 22:34:37 GMT</pubDate></item><item><title><![CDATA[Reply to Fehler im C++ International Standard? on Sun, 27 Sep 2009 12:41:24 GMT]]></title><description><![CDATA[<p>DeepCopy schrieb:</p>
<blockquote>
<p>Die Deduktion scheint immer angewandt zu werden, egal ob das mit den Funktionssignaturen nachher kompatibel ist oder nicht, d.h. wenn ich ein int übergebe und mein Parameter will T*, wird sich der Compiler nach der Deduktion beschweren.</p>
</blockquote>
<p>Er wird sich nur dann beschweren, wenn es sonst keine andere Funktion gibt, die aufgerufen werden kann. Es können auch nicht alle Typen deduziert werden. Beispiel:</p>
<pre><code class="language-cpp">template&lt;typename T&gt; struct identity {typedef T type;};

template&lt;typename T&gt; void foo(typename identity&lt;T&gt;::type x);

int main() {
  foo(4);       // Fehler! Compiler kann T nicht deduzieren, ignoriert
                // deswegen das Funktions-Template und findes keine
                // andere Funktion, die aufgerufen werden kann.

  foo&lt;int&gt;(23); // OK!
}
</code></pre>
<p>&quot;identity&lt;T&gt;::type&quot; ist für T kein &quot;deduzierbarer Kontext&quot;. Wichtig ist auch, dass wenn der Compiler versucht Template-Parameter zu deduzieren, und ein zu deduzierender Template-Parameter in mehreren &quot;deduzierbaren Kontexten&quot; auftaucht, die Dedukition fehlschlägt, falls er auf unterschiedliche Ergebnisse kommt. Beispiel</p>
<pre><code class="language-cpp">template&lt;typename T&gt; void bar(T x, T y);
template&lt;typename T&gt; void baz(T x, typename identity&lt;T&gt;::type y);

int main() {
  bar(3,24L); // Fehler! T nicht deduzierbar, weil einmal T=int
              // und dann T=long rauskommt

  baz(3,24L); // OK, T=int, 24L wird zu einem int implizit konvertiert.
}
</code></pre>
<p>DeepCopy schrieb:</p>
<blockquote>
<p>So weit, so gut. Aber: was ist wenn als Argument int&amp; und Parameter T* gefordert sind, oder auch anderes herum, wenn int* als Argument und Parameter T&amp; gefordert werden? Hier kann ich nicht &quot;Kürzen&quot; da einmal eine Referenz und einmal ein Zeiger vorhanden ist, was ist das Ergebnis der Deduktion? Bleibt &quot;int*&quot; oder &quot;int&amp;&quot;, darf hier die Spezialisierung angewendet werden?</p>
</blockquote>
<p>Da gibt es so einen Begriff: SFINAE = substitution failure is not an error. Wenn das Deduzieren nicht gelingt, wird das Template einfach ignoriert, ohne einen Fehler zu generieren. Wenn allerdings keine aufrufbare Funktion bzw Spezialisierung übrig bleibt und das &quot;overload set&quot; leer ist, gibt es natürlich einen Fehler beim Kompilieren.</p>
<p>Top-Level Referenzen werden mehr oder weniger bei der Deduktion ignoriert, bis auf dass array-to-pointer decay bzw function-to-pointer decay nicht sofort angewendet wird:</p>
<pre><code class="language-cpp">template&lt;typename T&gt; void dings(T);
template&lt;typename T&gt; void blah (T*);
template&lt;typename T&gt; void bums (T&amp;);
int main()
{
  int array[5];
  dings(array); // T = int*   --&gt; void dings(int*);
  blah (array); // T = int    --&gt; void blah (int*);
  bums (array); // T = int[5] --&gt; void bums (int(&amp;)[5]);
}
</code></pre>
<p>&quot;X-to-pointer decays&quot;, &quot;implicit cv qualification conversion&quot; und Konvertierung von Derived auf Base sind zulässig bei der Deduktion, alle anderen impliziten Konvertieren nicht.</p>
<p>Edit: Um die Beispiele zu vervollständigen:</p>
<pre><code class="language-cpp">template&lt;typename T&gt; struct A {};

struct B : A&lt;int&gt; {};

template&lt;typename T&gt;
void foo(A&lt;T&gt; const&amp; x) {}

int main() {
    B b;
    foo(b); // T = int
}
</code></pre>
<p>&quot;A&lt;T&gt; const&amp;&quot; ist für T ein deduzierbarer Kontext und die Deduktion gelingt auch dann, wenn foo mit einem abgeleiteten Objekt aufgerufen wird. Hier findet sowohl eine Derived-to-Base Konvertierung als auch eine &quot;cv qualification conversion&quot; statt.</p>
<p>Wer sich für all die Details interessiert, sollte sich <a href="https://duckduckgo.com/?q=isbn+9780201734843&amp;cppnetbooks" rel="nofollow">C++ Templates | ISBN: 9780201734843</a> mal anschauen. Ich kann das Buch nur empfehlen. Mir sind so einige Lichter beim Lesen aufgegangen.</p>
<p>Gruß,<br />
SP</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1784785</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1784785</guid><dc:creator><![CDATA[Sebastian Pizer]]></dc:creator><pubDate>Sun, 27 Sep 2009 12:41:24 GMT</pubDate></item></channel></rss>