<?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[Default-Typen und -Werte bei Funktions-Templates]]></title><description><![CDATA[<p>Hallo,</p>
<p>ich bin gerade an Funktions-Templates dran und habe ein Problem, bei dem ich nicht weiterkomme.</p>
<p>Ich habe mir ein paar Templates für das Finden des Medians einer unsortierten Reihe geschrieben. Die Funktionen erwarten zwei Iteratoren und eine Vergleichs-Funktion:</p>
<pre><code>//Median.h
#pragma once
template &lt;class Iterator, class Compare&gt;
Iterator spalte_auf(Iterator begin, Iterator end, Compare comp) {
    Iterator tind = begin + (end - begin) / 2;
    std::swap(*tind, *begin);
    for (tind = begin++; begin != end; ++begin) {
        if (comp(*begin, *tind)) {
            std::swap(*begin, *(tind + 1));
            std::swap(*tind, *(tind + 1));
            tind++;
        }
    }
    return tind;
}

template &lt;class Iterator, class Compare&gt;
Iterator finde_ktes(Iterator begin, Iterator end, int k, Compare comp){
    Iterator nbegin = begin;
    while (true){
        Iterator tind = spalte_auf(begin, end, comp);
        if (tind - nbegin &lt; k - 1) {
            begin = tind + 1;
        }
        else if (tind - nbegin &gt; k - 1) {
            end = tind;
        }
        else
            return tind;
    }
}

template &lt;class Iterator, class Compare&gt;
Iterator getMedian(Iterator begin, Iterator end, Compare comp) {
    return finde_ktes(begin, end, (end - begin) / 2, comp);
}
</code></pre>
<pre><code>//main.cpp
#include &lt;iostream&gt;
#include &lt;vector&gt;
#include &quot;Median.h&quot;
using namespace std;

int main(){

    vector&lt;unsigned&gt; data;
    data.push_back(7);	data.push_back(1);	data.push_back(4);
    data.push_back(8);	data.push_back(2);	data.push_back(9);
    data.push_back(5);	data.push_back(6);	data.push_back(3);

    cout &lt;&lt; *getMedian(data.begin(), data.end(), less&lt;unsigned&gt;()) &lt;&lt; endl;

    return EXIT_SUCCESS;
}
</code></pre>
<p>Jetzt wollte ich das ganze so erweitern, dass die Templates standarmäßig <code>std::less</code> verwenden und ich eine Funktion nur übergeben muss, wenn es eine andere sein soll. Ich konnte das bisher aber leider nur so lösen, dass ich jedes Template zweimal implementiere:</p>
<pre><code>template&lt;class Iterator&gt;
Iterator spalte_auf(Iterator begin, Iterator end) {
    return spalte_auf(begin, end, std::less&lt;decltype(*begin)&gt;());
}

template &lt;class Iterator&gt;
Iterator finde_ktes(Iterator begin, Iterator end, int k){
    return finde_ktes(begin, end, k, std::less&lt;decltype(*begin)&gt;());
}

template &lt;class Iterator&gt;
Iterator getMedian(Iterator begin, Iterator end) {
    return getMedian(begin, end, std::less&lt;decltype(*begin)&gt;());
}
</code></pre>
<p>Gibt es dafür noch eine andere/bessere Möglichkeit? Ich hatte an &quot;Standartwerte&quot;, wie bei Funktionen gedacht:</p>
<pre><code>//Median.h
template&lt;class Iterator, class Compare = decltype(std::less)&gt;
Iterator getMedian(Iterator begin, Iterator end, Compare comp = std::less&lt;decltype(*begin)&gt;()) {
    return finde_ktes(begin, end, (end - begin) / 2, comp);
}
</code></pre>
<p>Aber dann bekomme ich folgende Fehlermeldung:</p>
<p>1&gt; ...\main.cpp(55): error C2783: &quot;Iterator getMedian(Iterator,Iterator,Compare)&quot;: template-Argument für &quot;Compare&quot; konnte nicht hergeleitet werden.<br />
1&gt; ...\median.h(57): Siehe Deklaration von 'getMedian'</p>
<p>Ich vermute, dass es daran liegt, dass ich in der Zeile</p>
<pre><code>template&lt;class Iterator, class Compare = decltype(std::less)&gt;
</code></pre>
<p>noch den Typ von *begin brauche, aber wie komme ich da ran, ohne ihn extra mit zu übergen?</p>
<p>Kann mir jemand sagen ob, und wenn ja wie, das richtig geht?</p>
<p>Viele Grüße<br />
Matze</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/324242/default-typen-und-werte-bei-funktions-templates</link><generator>RSS for Node</generator><lastBuildDate>Tue, 14 Jul 2026 18:28:15 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/324242.rss" rel="self" type="application/rss+xml"/><pubDate>Sat, 08 Mar 2014 17:48:00 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Default-Typen und -Werte bei Funktions-Templates on Sat, 08 Mar 2014 17:51:09 GMT]]></title><description><![CDATA[<p>Hallo,</p>
<p>ich bin gerade an Funktions-Templates dran und habe ein Problem, bei dem ich nicht weiterkomme.</p>
<p>Ich habe mir ein paar Templates für das Finden des Medians einer unsortierten Reihe geschrieben. Die Funktionen erwarten zwei Iteratoren und eine Vergleichs-Funktion:</p>
<pre><code>//Median.h
#pragma once
template &lt;class Iterator, class Compare&gt;
Iterator spalte_auf(Iterator begin, Iterator end, Compare comp) {
    Iterator tind = begin + (end - begin) / 2;
    std::swap(*tind, *begin);
    for (tind = begin++; begin != end; ++begin) {
        if (comp(*begin, *tind)) {
            std::swap(*begin, *(tind + 1));
            std::swap(*tind, *(tind + 1));
            tind++;
        }
    }
    return tind;
}

template &lt;class Iterator, class Compare&gt;
Iterator finde_ktes(Iterator begin, Iterator end, int k, Compare comp){
    Iterator nbegin = begin;
    while (true){
        Iterator tind = spalte_auf(begin, end, comp);
        if (tind - nbegin &lt; k - 1) {
            begin = tind + 1;
        }
        else if (tind - nbegin &gt; k - 1) {
            end = tind;
        }
        else
            return tind;
    }
}

template &lt;class Iterator, class Compare&gt;
Iterator getMedian(Iterator begin, Iterator end, Compare comp) {
    return finde_ktes(begin, end, (end - begin) / 2, comp);
}
</code></pre>
<pre><code>//main.cpp
#include &lt;iostream&gt;
#include &lt;vector&gt;
#include &quot;Median.h&quot;
using namespace std;

int main(){

    vector&lt;unsigned&gt; data;
    data.push_back(7);	data.push_back(1);	data.push_back(4);
    data.push_back(8);	data.push_back(2);	data.push_back(9);
    data.push_back(5);	data.push_back(6);	data.push_back(3);

    cout &lt;&lt; *getMedian(data.begin(), data.end(), less&lt;unsigned&gt;()) &lt;&lt; endl;

    return EXIT_SUCCESS;
}
</code></pre>
<p>Jetzt wollte ich das ganze so erweitern, dass die Templates standarmäßig <code>std::less</code> verwenden und ich eine Funktion nur übergeben muss, wenn es eine andere sein soll. Ich konnte das bisher aber leider nur so lösen, dass ich jedes Template zweimal implementiere:</p>
<pre><code>template&lt;class Iterator&gt;
Iterator spalte_auf(Iterator begin, Iterator end) {
    return spalte_auf(begin, end, std::less&lt;decltype(*begin)&gt;());
}

template &lt;class Iterator&gt;
Iterator finde_ktes(Iterator begin, Iterator end, int k){
    return finde_ktes(begin, end, k, std::less&lt;decltype(*begin)&gt;());
}

template &lt;class Iterator&gt;
Iterator getMedian(Iterator begin, Iterator end) {
    return getMedian(begin, end, std::less&lt;decltype(*begin)&gt;());
}
</code></pre>
<p>Gibt es dafür noch eine andere/bessere Möglichkeit? Ich hatte an &quot;Standartwerte&quot;, wie bei Funktionen gedacht:</p>
<pre><code>//Median.h
template&lt;class Iterator, class Compare = decltype(std::less)&gt;
Iterator getMedian(Iterator begin, Iterator end, Compare comp = std::less&lt;decltype(*begin)&gt;()) {
    return finde_ktes(begin, end, (end - begin) / 2, comp);
}
</code></pre>
<p>Aber dann bekomme ich folgende Fehlermeldung:</p>
<p>1&gt; ...\main.cpp(55): error C2783: &quot;Iterator getMedian(Iterator,Iterator,Compare)&quot;: template-Argument für &quot;Compare&quot; konnte nicht hergeleitet werden.<br />
1&gt; ...\median.h(57): Siehe Deklaration von 'getMedian'</p>
<p>Ich vermute, dass es daran liegt, dass ich in der Zeile</p>
<pre><code>template&lt;class Iterator, class Compare = decltype(std::less)&gt;
</code></pre>
<p>noch den Typ von *begin brauche, aber wie komme ich da ran, ohne ihn extra mit zu übergen?</p>
<p>Kann mir jemand sagen ob, und wenn ja wie, das richtig geht?</p>
<p>Viele Grüße<br />
Matze</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2387683</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2387683</guid><dc:creator><![CDATA[MatzeHHC]]></dc:creator><pubDate>Sat, 08 Mar 2014 17:51:09 GMT</pubDate></item><item><title><![CDATA[Reply to Default-Typen und -Werte bei Funktions-Templates on Sat, 08 Mar 2014 17:59:46 GMT]]></title><description><![CDATA[<p>Dir ist schon klar, dass std::nth_element dir den Median in O(n) gibt anstelle in O(n^2) wie bei deiner Implementierung?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2387684</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2387684</guid><dc:creator><![CDATA[nth_user]]></dc:creator><pubDate>Sat, 08 Mar 2014 17:59:46 GMT</pubDate></item><item><title><![CDATA[Reply to Default-Typen und -Werte bei Funktions-Templates on Sat, 08 Mar 2014 18:04:15 GMT]]></title><description><![CDATA[<p>Btw</p>
<pre><code class="language-cpp">template&lt;class Iterator, class Compare = decltype(std::less&lt;std::decay&lt;decltype(*std::declval&lt;Iterator&gt;())&gt;::type&gt;
Iterator getMedian(Iterator begin, Iterator end, Compare comp = std::less&lt;decltype(*begin)&gt;()) {
    return finde_ktes(begin, end, (end - begin) / 2, comp);
}
</code></pre>
<p>könnte gehen.</p>
<p>Viel einfacher ist aber eine Überladung</p>
<pre><code class="language-cpp">template&lt;class Iterator&gt;
Iterator getMedian(Iterator begin, Iterator end) {
    return finde_ktes(begin, end, (end - begin) / 2, std::less&lt;decltype(*begin)&gt;);
}

template&lt;class Iterator, class Compare&gt;
Iterator getMedian(Iterator begin, Iterator end, Compare comp) {
    return finde_ktes(begin, end, (end - begin) / 2, comp);
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2387686</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2387686</guid><dc:creator><![CDATA[nth_user]]></dc:creator><pubDate>Sat, 08 Mar 2014 18:04:15 GMT</pubDate></item><item><title><![CDATA[Reply to Default-Typen und -Werte bei Funktions-Templates on Sat, 08 Mar 2014 18:06:36 GMT]]></title><description><![CDATA[<p>nth_user schrieb:</p>
<blockquote>
<p>Dir ist schon klar, dass std::nth_element dir den Median in O(n) gibt anstelle in O(n^2) wie bei deiner Implementierung?</p>
</blockquote>
<p>1. Vergleichst du gerade den mittleren Aufwand von nth_element mit dem maximalen Aufwand meines Algoritmus, was wohl etwas unfair ist.</p>
<p>2. Darum geht es hier doch gar nicht...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2387687</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2387687</guid><dc:creator><![CDATA[MatzeHHC]]></dc:creator><pubDate>Sat, 08 Mar 2014 18:06:36 GMT</pubDate></item><item><title><![CDATA[Reply to Default-Typen und -Werte bei Funktions-Templates on Sat, 08 Mar 2014 18:09:55 GMT]]></title><description><![CDATA[<p>nth_user schrieb:</p>
<blockquote>
<p>Viel einfacher ist aber eine Überladung</p>
</blockquote>
<p>Hatte ich auch schon überlegt, dann habe ich aber viel doppelten Code.</p>
<p>Das andere muss ich erst mal nachvollziehen.</p>
<p>Danke!</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2387688</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2387688</guid><dc:creator><![CDATA[MatzeHHC]]></dc:creator><pubDate>Sat, 08 Mar 2014 18:09:55 GMT</pubDate></item><item><title><![CDATA[Reply to Default-Typen und -Werte bei Funktions-Templates on Sat, 08 Mar 2014 18:11:50 GMT]]></title><description><![CDATA[<p>MatzeHHC schrieb:</p>
<blockquote>
<p>Hatte ich auch schon überlegt, dann habe ich aber viel doppelten Code.</p>
</blockquote>
<p>Hast du nicht, wenn die eine Funktion die andere aufruft. Codeduplizierung ist anders.</p>
<p>Ich würde auch Überladung nehmen. Ist einfacher, lesbarer, wartbarer und löst keinen Augenkrebs aus.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2387689</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2387689</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Sat, 08 Mar 2014 18:11:50 GMT</pubDate></item><item><title><![CDATA[Reply to Default-Typen und -Werte bei Funktions-Templates on Sat, 08 Mar 2014 18:13:35 GMT]]></title><description><![CDATA[<pre><code>decltype(std::less&lt;std::decay&lt;decltype(*std::declval&lt;Iterator&gt;())&gt;::type
</code></pre>
<p><img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/27a1.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--right_arrow"
      title=":arrow_right:"
      alt="➡"
    /></p>
<pre><code>std::less&lt;typename std::iterator_traits&lt;Iterator&gt;::value_type&gt;
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2387692</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2387692</guid><dc:creator><![CDATA[Columbo]]></dc:creator><pubDate>Sat, 08 Mar 2014 18:13:35 GMT</pubDate></item><item><title><![CDATA[Reply to Default-Typen und -Werte bei Funktions-Templates on Sat, 08 Mar 2014 18:22:44 GMT]]></title><description><![CDATA[<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/12954">@Nexus</a>: Wenn man das fertigstellt, sieht es so aus:</p>
<pre><code>template&lt; typename RandomIter,
          typename Compare = std::less&lt;typename std::iterator_traits&lt;RandomIter&gt;::value_type&gt; &gt;
RandomIter getMedian( RandomIter begin, RandomIter end, Compare comp = {} )
{
	auto mid_iter = begin + (end - begin)/2;
	std::nth_element(begin, mid_iter, end, comp);
	return mid_iter;
}
</code></pre>
<p>Findest du das tatsächlich hässlich?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2387696</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2387696</guid><dc:creator><![CDATA[Columbo]]></dc:creator><pubDate>Sat, 08 Mar 2014 18:22:44 GMT</pubDate></item><item><title><![CDATA[Reply to Default-Typen und -Werte bei Funktions-Templates on Sat, 08 Mar 2014 18:25:32 GMT]]></title><description><![CDATA[<p>Arcoth schrieb:</p>
<blockquote>
<pre><code>std::less&lt;typename std::iterator_traits&lt;Iterator&gt;::value_type&gt;
</code></pre>
</blockquote>
<p>Danke, so geht es! (zumindest, wenn ich das gleiche Konstrukt dann im Funktionskopf verwende:</p>
<pre><code>template&lt;class Iterator, class Compare = std::less&lt;typename std::iterator_traits&lt;Iterator&gt;::value_type&gt;&gt;
Iterator getMedian(Iterator begin, Iterator end, Compare comp = std::less&lt;typename std::iterator_traits&lt;Iterator&gt;::value_type&gt;()) {
    return finde_ktes(begin, end, (end - begin) / 2, comp);
}
</code></pre>
<p>Das ist wahrscheinlich auch besser so, da</p>
<pre><code>decltype(*begin)
</code></pre>
<p>unsigned&amp; statt unsigned liefert...</p>
<p>Nexus schrieb:</p>
<blockquote>
<p>MatzeHHC schrieb:</p>
<blockquote>
<p>Hatte ich auch schon überlegt, dann habe ich aber viel doppelten Code.</p>
</blockquote>
<p>Hast du nicht, wenn die eine Funktion die andere aufruft. Codeduplizierung ist anders.</p>
<p>Ich würde auch Überladung nehmen. Ist einfacher, lesbarer, wartbarer und löst keinen Augenkrebs aus.</p>
</blockquote>
<p>Stimmt, ich war gerade verwirrt, weil nth_user wirklich die Funktionen 2 mal geschrieben hat.</p>
<p>Was ich jetzt besser finde weiß ich aber noch nicht <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f603.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--grinning_face_with_big_eyes"
      title=":D"
      alt="😃"
    /></p>
<p>Danke für eure Hilfe!</p>
<p>Gruß<br />
Matze</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2387698</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2387698</guid><dc:creator><![CDATA[MatzeHHC]]></dc:creator><pubDate>Sat, 08 Mar 2014 18:25:32 GMT</pubDate></item><item><title><![CDATA[Reply to Default-Typen und -Werte bei Funktions-Templates on Sat, 08 Mar 2014 18:28:54 GMT]]></title><description><![CDATA[<blockquote>
<p>zumindest, wenn ich das gleiche Konstrukt dann im Funktionskopf verwende:</p>
</blockquote>
<p>Warum nicht einfach {}? Lass mich raten: VC++?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2387699</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2387699</guid><dc:creator><![CDATA[Columbo]]></dc:creator><pubDate>Sat, 08 Mar 2014 18:28:54 GMT</pubDate></item><item><title><![CDATA[Reply to Default-Typen und -Werte bei Funktions-Templates on Sat, 08 Mar 2014 18:33:45 GMT]]></title><description><![CDATA[<p>Arcoth schrieb:</p>
<blockquote>
<p>Warum nicht einfach {}? Lass mich raten: VC++?</p>
</blockquote>
<p>Die Schreibweise kenne ich nicht <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f62e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_with_open_mouth"
      title=":open_mouth:"
      alt="😮"
    /><br />
Was bedeutet das?</p>
<p>Funktioniert aber (Visual Studio 2013).</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2387701</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2387701</guid><dc:creator><![CDATA[MatzeHHC]]></dc:creator><pubDate>Sat, 08 Mar 2014 18:33:45 GMT</pubDate></item><item><title><![CDATA[Reply to Default-Typen und -Werte bei Funktions-Templates on Sat, 08 Mar 2014 18:37:46 GMT]]></title><description><![CDATA[<p>Arcoth schrieb:</p>
<blockquote>
<p>Findest du das tatsächlich hässlich?</p>
</blockquote>
<p>Man braucht doch eine gewisse Zeit, um anhand der Signatur herauszufinden, wie die Funktion aufgerufen werden kann. Aber das geht noch im Vergleich zu nth_users Version.</p>
<p>Muss bei deinem Code <code>Compare</code> nicht default-konstruierbar sein? Das könnte eine unnötige Einschränkung darstellen...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2387702</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2387702</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Sat, 08 Mar 2014 18:37:46 GMT</pubDate></item><item><title><![CDATA[Reply to Default-Typen und -Werte bei Funktions-Templates on Sat, 08 Mar 2014 18:48:43 GMT]]></title><description><![CDATA[<blockquote>
<p>Was bedeutet das?</p>
</blockquote>
<p>Das nennt sich <em>list-initialization</em>. In diesem Fall führt es dazu, dass der Default-Konstruktor aufgerufen wird (falls vorhanden und implizit aufrufbar).</p>
<blockquote>
<p>Muss bei deinem Code Compare nicht default-konstruierbar sein?</p>
</blockquote>
<p>Nein <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
<p>§14.7.1/3 schrieb:</p>
<blockquote>
<p>Unless a call is to a function template explicit specialization [...], a default argument for a function template [..] is implicitly instantiated when the function is called in a context that requires the value of the default argument.</p>
</blockquote>
<pre><code>struct A
{
	A(int){}
	A() = delete;
};

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

int main()
{
	F( A{4} );
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2387707</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2387707</guid><dc:creator><![CDATA[Columbo]]></dc:creator><pubDate>Sat, 08 Mar 2014 18:48:43 GMT</pubDate></item></channel></rss>