<?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[Auswahl einer überladenen Methode]]></title><description><![CDATA[<p>Hallo,</p>
<p>ich verstehe hier nicht, warum der Compiler in diesem Beispiel immer die Variante #2 aufruft. Kann mir jemand sagen, warum?</p>
<pre><code>#include &lt;iostream&gt;

using namespace std;

template&lt;typename T, unsigned int N&gt;
struct Base
{
	Base()
	{
	}

    // Variante 1
	Base&amp; operator+=( const Base&amp; rhs )
	{
		cout &lt;&lt; &quot;Base&amp; operator+=( const Base&amp; rhs ) called&quot; &lt;&lt; endl;
		return *this;
	}

    // Variante 2
	template&lt;typename U&gt;
	Base&amp; operator+=( const U&amp; rhs )
	{
		cout &lt;&lt; &quot;Base&amp; operator+=( const U&amp; rhs ) called&quot; &lt;&lt; endl;
		return *this;
	}

    // Variante 3
	template&lt;typename U&gt;
	Base&amp; operator+=( const Base&lt;U,N&gt;&amp; rhs )
	{
		cout &lt;&lt; &quot;Base&amp; operator+=( const Base&lt;U,N&gt;&amp; rhs ) called&quot; &lt;&lt; endl;
		return *this;
	}
};

template&lt;typename T&gt;
struct Derived : public Base&lt;T,1&gt;
{
	using Base&lt;T,1&gt;::operator+=;

	Derived()
	{
	}
};

int main( int argc, char* argv[] )
{
   Derived&lt;int&gt; d1;
   Derived&lt;int&gt; d2;
   Derived&lt;double&gt; d3;

   d1 += d2; // soll Variante #1 aufrufen, ruft aber #2 auf
   d1 += 2;  // soll Variante #2 aufrufen
   d1 += d3; // soll Variante #3 aufrufen, ruft aber #2 auf

   return 0;
}
</code></pre>
<p>Wie bringe ich den Compiler dazu, die entsprechende Variante aufzurufen?</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/338842/auswahl-einer-überladenen-methode</link><generator>RSS for Node</generator><lastBuildDate>Mon, 13 Apr 2026 03:17:27 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/338842.rss" rel="self" type="application/rss+xml"/><pubDate>Thu, 14 Jul 2016 15:17:00 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Auswahl einer überladenen Methode on Thu, 14 Jul 2016 15:23:09 GMT]]></title><description><![CDATA[<p>Hallo,</p>
<p>ich verstehe hier nicht, warum der Compiler in diesem Beispiel immer die Variante #2 aufruft. Kann mir jemand sagen, warum?</p>
<pre><code>#include &lt;iostream&gt;

using namespace std;

template&lt;typename T, unsigned int N&gt;
struct Base
{
	Base()
	{
	}

    // Variante 1
	Base&amp; operator+=( const Base&amp; rhs )
	{
		cout &lt;&lt; &quot;Base&amp; operator+=( const Base&amp; rhs ) called&quot; &lt;&lt; endl;
		return *this;
	}

    // Variante 2
	template&lt;typename U&gt;
	Base&amp; operator+=( const U&amp; rhs )
	{
		cout &lt;&lt; &quot;Base&amp; operator+=( const U&amp; rhs ) called&quot; &lt;&lt; endl;
		return *this;
	}

    // Variante 3
	template&lt;typename U&gt;
	Base&amp; operator+=( const Base&lt;U,N&gt;&amp; rhs )
	{
		cout &lt;&lt; &quot;Base&amp; operator+=( const Base&lt;U,N&gt;&amp; rhs ) called&quot; &lt;&lt; endl;
		return *this;
	}
};

template&lt;typename T&gt;
struct Derived : public Base&lt;T,1&gt;
{
	using Base&lt;T,1&gt;::operator+=;

	Derived()
	{
	}
};

int main( int argc, char* argv[] )
{
   Derived&lt;int&gt; d1;
   Derived&lt;int&gt; d2;
   Derived&lt;double&gt; d3;

   d1 += d2; // soll Variante #1 aufrufen, ruft aber #2 auf
   d1 += 2;  // soll Variante #2 aufrufen
   d1 += d3; // soll Variante #3 aufrufen, ruft aber #2 auf

   return 0;
}
</code></pre>
<p>Wie bringe ich den Compiler dazu, die entsprechende Variante aufzurufen?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2502353</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2502353</guid><dc:creator><![CDATA[DocShoe]]></dc:creator><pubDate>Thu, 14 Jul 2016 15:23:09 GMT</pubDate></item><item><title><![CDATA[Reply to Auswahl einer überladenen Methode on Thu, 14 Jul 2016 15:49:29 GMT]]></title><description><![CDATA[<p>Machst halt ne Vorwärtsdeklaration von Derived und noch einen Operator dazu.<br />
Google mal nach &quot;c++ overload resolution&quot; oder so. Da müsste schon was bei rauskommen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2502359</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2502359</guid><dc:creator><![CDATA[funda]]></dc:creator><pubDate>Thu, 14 Jul 2016 15:49:29 GMT</pubDate></item><item><title><![CDATA[Reply to Auswahl einer überladenen Methode on Thu, 14 Jul 2016 15:58:17 GMT]]></title><description><![CDATA[<p>Ansonsten hier noch ein Video zu Thema: <a href="https://www.youtube.com/watch?v=03KAWd6Yp8I" rel="nofollow">https://www.youtube.com/watch?v=03KAWd6Yp8I</a></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2502362</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2502362</guid><dc:creator><![CDATA[wob]]></dc:creator><pubDate>Thu, 14 Jul 2016 15:58:17 GMT</pubDate></item><item><title><![CDATA[Reply to Auswahl einer überladenen Methode on Thu, 14 Jul 2016 17:39:29 GMT]]></title><description><![CDATA[<p>bist du sicher, dass du so einfach die operatoren aus der Basisklasse in derived verwenden willst? das sieht mir ziemlich gefährlich und nach slicing aus...</p>
<p>ansonsten kannst du dir ja die eine funktion ja so hinbiegen, dass sie deinen eigenen &quot;regeln&quot; entspricht:</p>
<pre><code class="language-cpp">#include &lt;type_traits&gt;

//Variante 2
template&lt;typename U&gt; 
std::enable_if_t&lt;
  !std::is_base_of&lt;Base, U&gt;::value
  &amp;&amp; std::is_same&lt;T, U&gt;::value, 
  Base&amp;&gt;
    operator+=( const U&amp; rhs ) 
    { 
        cout &lt;&lt; &quot;Base&amp; operator+=( const U&amp; rhs ) called&quot; &lt;&lt; endl; 
        return *this; 
    }
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2502374</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2502374</guid><dc:creator><![CDATA[dove]]></dc:creator><pubDate>Thu, 14 Jul 2016 17:39:29 GMT</pubDate></item><item><title><![CDATA[Reply to Auswahl einer überladenen Methode on Fri, 15 Jul 2016 07:50:52 GMT]]></title><description><![CDATA[<p>Vielleicht funktioniert das Ganze doch nicht so, wie ich mir das vorstelle. Im Prinzip habe ich folgendes vor: Ich möchte mehrdimensionale Arrays als Klassen kapseln, dazu gibt es eine Klasse <code>ArrayBase</code> .</p>
<pre><code>#include &lt;array&gt;
#include &lt;vector&gt;

template&lt;typename T,unsigned int N&gt;
class ArrayBase
{
   std::vector&lt;T&gt;              Elements_; // Elemente des Arrays
   std::array&lt;std::size_t,N&gt;   Extents_;  // Größe der einzelnen Dimensionen
   std::array&lt;std::size_t,N&gt;   Strides_;  // Offset für nächstes Element in der gleichen Dimension

public:
   ArrayBase()
   {
   }

   virtual ~ArrayBase()
   {
   }

   ... div. Methoden wie size(), empty(), clear(), etc. Was man halt von der
   STL so kennt.
};
</code></pre>
<p>Davon leitet die Spezialisierung für ein 2-dimensionales Array ab, die Methoden mitbringt, die nur für 2D Arrays vorgesehen sind:</p>
<pre><code>template&lt;typename T&gt;
class Array2D : public ArrayBase&lt;T,2&gt;
{
public:
   Array2D()
   {
   }

   // Größe des Arrays setzen
   void resize( std::size_t d0, std::size_t d1 )
   {
      ...
   }

   T&amp; operator()( std::size_t d0, std::size_t d1 )
   {
      ...
   }

   const T&amp; operator()( std::size_t d0, std::size_t d1 ) const
   {
      ...
   }
};
</code></pre>
<p>Nun möchte ich Rechenoperationen auf dem Array zulassen, z.B. die Addition eines anderen Arrays oder eines einzelnen Wertes. Effektiv ist das einfach nur das Addieren der einzelnen Arrayelemente/Werte, unabhänigig von der Anzahl der Dimensionen. Also sollte das in der Basisklasse implementiert werden können. Ich brauche dazu für jede Addition drei Überladungen, eine für Skalare und zwei für Arrays (gleicher Datentyp/anderer, konvertierbarer Datentyp).</p>
<pre><code>template&lt;typename T,unsigned int N&gt;
class ArrayBase
{
   ...

public:
   ArrayBase&amp; operator+=( const ArrayBase&amp; rhs )
   {
      // Arrayelemente aufaddieren
      return *this;
   }

   template&lt;typename U&gt;
   ArrayBase&amp; operator+=( const ArrayBase&lt;U,N&gt;&amp; rhs )
   {
      // Arrayelemente aufaddieren
      return *this;
   }

   template&lt;typename U&gt;
   ArrayBase&amp; operator+=( const U&amp; rhs )
   {
      // Wert zu Arrayelementen addieren
      return *this;
   }
};

// freie Funktionen
template&lt;typename T,unsigned int N&gt;
ArrayBase&lt;T,N&gt; operator+( const ArrayBase&lt;T,N&gt;&amp; lhs, const ArrayBase&lt;T,N&gt;&amp; rhs )
{
   ArrayBase&lt;T,N&gt; tmp( lhs );
   return tmp += rhs;
}

template&lt;typename T,typename U,unsigned int N&gt;
ArrayBase&lt;T,N&gt; operator+( const ArrayBase&lt;T,N&gt;&amp; lhs, const ArrayBase&lt;U,N&gt;&amp; rhs )
{
   ArrayBase&lt;T,N&gt; tmp( lhs );
   return tmp += rhs;
}

template&lt;typename T,typename U,unsigned int N&gt;
ArrayBase&lt;T,N&gt; operator+( const ArrayBase&lt;T,N&gt;&amp; lhs, const U&amp; rhs )
{
   ArrayBase&lt;T,N&gt; tmp( lhs );
   return tmp += rhs;
}

template&lt;typename T,typename U,unsigned int N&gt;
ArrayBase&lt;T,N&gt; operator+( const U&amp; lhs, const ArrayBase&lt;T,N&gt;&amp; rhs )
{
   return rhs + lhs;
}
</code></pre>
<p>Diese ganzen Operationen möchte ich jetzt nicht für alle Array Varianten wiederholen. Vielleicht ist der Ansatz auch Murks, oder ich muss wirklich alles für jede Variante wiederholen <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f61e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--disappointed_face"
      title=":("
      alt="😞"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2502422</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2502422</guid><dc:creator><![CDATA[DocShoe]]></dc:creator><pubDate>Fri, 15 Jul 2016 07:50:52 GMT</pubDate></item><item><title><![CDATA[Reply to Auswahl einer überladenen Methode on Fri, 15 Jul 2016 08:53:12 GMT]]></title><description><![CDATA[<p>zum design: ich würde vorsichtiger sein. was du vorhast, sieht nicht (unbedingt) nach vererbung aus.</p>
<p>vielleicht so:</p>
<pre><code class="language-cpp">template &lt;class T, int N&gt;
class ArrayImpl { 
   //hier alle funktionen, die allgemein für arrays interessant sind
};

template &lt;class T, class Impl&gt;
class ArrayBase : private Impl { 
//so kommst du nicht so leicht in die verlegenheit, hier sachen zu nutzen, die von einem bestimmten N abhängen

protected:
  ArrayImpl&amp; get_impl() { return *this; }
  //hier tatsächlich nur funktionen, die mit für alle arrays erlaubt sind
};

template &lt;class T&gt;
class Array2D : public ArrayBase&lt;T, ArrayImpl&lt;T,2&gt;&gt; {

}
</code></pre>
<p>ansonsten zur überladung willst du wahrscheinlich genau so etwas:</p>
<pre><code class="language-cpp">template &lt;class U&gt;
enable_if_t&lt;is_scalar&lt;U&gt;::value&gt; operator+=(U const&amp; something)
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2502432</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2502432</guid><dc:creator><![CDATA[dove]]></dc:creator><pubDate>Fri, 15 Jul 2016 08:53:12 GMT</pubDate></item><item><title><![CDATA[Reply to Auswahl einer überladenen Methode on Fri, 15 Jul 2016 11:58:04 GMT]]></title><description><![CDATA[<p>Ich denke schon, dass Vererbung hier richtig ist. Ein n-dimensionales Array <strong>ist</strong> ein generisches Array. In den abgeleiteten Klasse müssten eigentlich nur 5 Methoden ergänzt werden:</p>
<ul>
<li><code>resize(...)</code> mit der entsprechenden Anzahl der Parameter</li>
<li><code>operator()(...)</code> mit der entsprechenden Anzahl der Parameter (const + nonconst)</li>
<li><code>at(...)</code> mit der entsprechenden Anzahl der Parameter (const + nonconst)</li>
</ul>
<p>Nur muss ich jetzt wohl für jede Ableitung die mathematischen Operationen anbieten. Irgendwie unbefriedigend.</p>
<p>Vielleicht kann man mit eigenen Type Traits noch was basteln...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2502454</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2502454</guid><dc:creator><![CDATA[DocShoe]]></dc:creator><pubDate>Fri, 15 Jul 2016 11:58:04 GMT</pubDate></item><item><title><![CDATA[Reply to Auswahl einer überladenen Methode on Fri, 15 Jul 2016 13:15:00 GMT]]></title><description><![CDATA[<p>hm, alle drei methoden könntest du auch mit variadic templates für jede multi-array-klasse anbieten.</p>
<pre><code class="language-cpp">template &lt;typename... D&gt;
    auto resize (D ... d) -&gt; 
        enable_if_t&lt;
                    sizeof...(D)==Dim
                    //C++17: &amp;&amp; (is_convertible&lt;D, size_t&gt;::value &amp;&amp; ...)&gt; 
                   &gt;

    { 
        cout &lt;&lt; &quot;MultiArray&lt;T,Dim&gt;::resize\n&quot;;
    }
</code></pre>
<p>ein zweidimensionales array ist nur deshalb ein generisches array, weil die dimension des generischen arrays auf zwei fixiert ist.<br />
was du eigentlich willst, ist eine (template-) spezialisierung des templates für Dim=2 ohne dinge doppelt zu implementieren, und mit der richtigen automatischen namensauflösung. dafür könntest du diese klassenhierarchie verwenden:</p>
<pre><code class="language-cpp">//gemeinsame funktionen, eher intern
template &lt;class T, int Dim&gt;
class MultiArrayBase {
protected:
   vector&lt;T&gt; elements;
   array&lt;size_t, Dim&gt; extends;
};

//generisch
template &lt;class T, int Dim&gt;
class MultiArrayImpl : public MultiArrayBase&lt;T, Dim&gt; {
public:
    template &lt;typename... D&gt;
    auto resize (D ... d) -&gt; 
        enable_if_t&lt;
                    sizeof...(D)==Dim
                   &gt;

    { 
        cout &lt;&lt; &quot;MultiArray&lt;T,Dim&gt;::resize\n&quot;;
    }
};

//speziell
template &lt;class T&gt;
class MultiArrayImpl&lt;T, 2&gt; : public MultiArrayBase&lt;T, 2&gt; {
public:
   auto resize (size_t d0, size_t d1)
   {
        cout &lt;&lt; &quot;MultiArray&lt;T, 2&gt;::resize\n&quot;;
   }
};

//öffentliches interface
template &lt;class T, int Dim&gt;
class MultiArray final : public MultiArrayImpl&lt;T, Dim&gt; {
public:
    MultiArray&amp; operator+= (MultiArray const&amp; other) {
        cout &lt;&lt; &quot;+= other\n&quot;;
        return *this;
    }

    template &lt;class U&gt;
    MultiArray&amp; operator+= (U const&amp; something) {
        cout &lt;&lt; &quot;+= something\n&quot;;
        return *this;
    }

    template &lt;class U&gt;
    MultiArray&amp; operator+= (MultiArray&lt;U, Dim&gt; const&amp; other) {
        cout &lt;&lt; &quot;+= other-convert\n&quot;;
        return *this;
    }
};

//extra-name
template &lt;class T&gt;
using MultiArray2D = MultiArray&lt;T, 2&gt;;

int main () {
    MultiArray&lt;int, 4&gt; arr;
    arr.resize(1, 2, 3, 4);

    MultiArray&lt;int, 2&gt; d1;
    MultiArray&lt;int, 2&gt; d2;
    MultiArray&lt;double, 2&gt; d3;

    d1.resize(1, 2);

    d1 += d2;
    d1 += 2;
    d1 += d3;
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2502463</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2502463</guid><dc:creator><![CDATA[dove]]></dc:creator><pubDate>Fri, 15 Jul 2016 13:15:00 GMT</pubDate></item><item><title><![CDATA[Reply to Auswahl einer überladenen Methode on Fri, 15 Jul 2016 14:12:56 GMT]]></title><description><![CDATA[<p>Hui, danke. Das muss ich mir mal in Ruhe zu Gemüte führen.</p>
<p>Nicht schlecht, die Spezialisierung zwischenzuschieben. Nu hab ich´s auch verstanden.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2502464</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2502464</guid><dc:creator><![CDATA[DocShoe]]></dc:creator><pubDate>Fri, 15 Jul 2016 14:12:56 GMT</pubDate></item></channel></rss>