<?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[virtuelles Methoden-Template]]></title><description><![CDATA[<p>Ich hätte gerne eine abstrakte Basisklasse mit einer virtuellen Methode:</p>
<pre><code>template &lt;class Random&gt;
virtual void foo(Random&amp; rnd) = 0;
</code></pre>
<p>Dabei soll das Template Random für ein Objekt stehen, dass über operator() Zufallszahlen erzeugt. Das kompiliert jedoch nicht.</p>
<p>Mein erster Ansatz war sowas hier:</p>
<pre><code>virtual void foo(std::function&lt;size_t()&gt; rnd) = 0;
</code></pre>
<p>Allerdings wird beim Aufruf</p>
<pre><code>std::mt19937 rnd;
object.foo(rnd);
</code></pre>
<p>eine Kopie von rnd erzeugt, was bei Zufallsgeneratoren natürlich ziemlich unschön ist, wenn man denselben Generator erneut verwenden möchte.</p>
<p>Wie könnte man das Problem umgehen?</p>
<p>Dasselbe Problem habe ich bei</p>
<pre><code>template &lt;class Point&gt;
virtual void bar(Point&amp; p) = 0;
</code></pre>
<p>wobei p den operator[] überlädt. Als Point könnte man somit z.B. int* oder std::vector&lt;int&gt; einsetzen. Gibt es hier die Möglichkeit selbst eine Art Wrapper wie std::function zu schreiben? Und wenn ja wie? Oder gibt es vielleicht schon eine Lösung in der STL oder ggf. auch in Boost?</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/325977/virtuelles-methoden-template</link><generator>RSS for Node</generator><lastBuildDate>Sat, 11 Jul 2026 14:44:28 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/325977.rss" rel="self" type="application/rss+xml"/><pubDate>Mon, 26 May 2014 16:22:42 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to virtuelles Methoden-Template on Mon, 26 May 2014 16:22:42 GMT]]></title><description><![CDATA[<p>Ich hätte gerne eine abstrakte Basisklasse mit einer virtuellen Methode:</p>
<pre><code>template &lt;class Random&gt;
virtual void foo(Random&amp; rnd) = 0;
</code></pre>
<p>Dabei soll das Template Random für ein Objekt stehen, dass über operator() Zufallszahlen erzeugt. Das kompiliert jedoch nicht.</p>
<p>Mein erster Ansatz war sowas hier:</p>
<pre><code>virtual void foo(std::function&lt;size_t()&gt; rnd) = 0;
</code></pre>
<p>Allerdings wird beim Aufruf</p>
<pre><code>std::mt19937 rnd;
object.foo(rnd);
</code></pre>
<p>eine Kopie von rnd erzeugt, was bei Zufallsgeneratoren natürlich ziemlich unschön ist, wenn man denselben Generator erneut verwenden möchte.</p>
<p>Wie könnte man das Problem umgehen?</p>
<p>Dasselbe Problem habe ich bei</p>
<pre><code>template &lt;class Point&gt;
virtual void bar(Point&amp; p) = 0;
</code></pre>
<p>wobei p den operator[] überlädt. Als Point könnte man somit z.B. int* oder std::vector&lt;int&gt; einsetzen. Gibt es hier die Möglichkeit selbst eine Art Wrapper wie std::function zu schreiben? Und wenn ja wie? Oder gibt es vielleicht schon eine Lösung in der STL oder ggf. auch in Boost?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2400936</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2400936</guid><dc:creator><![CDATA[Ramanujan]]></dc:creator><pubDate>Mon, 26 May 2014 16:22:42 GMT</pubDate></item><item><title><![CDATA[Reply to virtuelles Methoden-Template on Mon, 26 May 2014 16:32:41 GMT]]></title><description><![CDATA[<p>virtuelle Methoden können kein Template sein, das nervt mich auch von Zeit zu Zeit.<br />
Das, was std::function macht ist Type-Erasure.<br />
Für deinen Punkt geht das auch, grob so:<br />
template &lt;typename Ret, typename Arg&gt;</p>
<pre><code>class indexable
{
public:
	template &lt;typename T&gt;
	indexable(T &amp;t)
	: base_(new basic_indexable&lt;T&gt;(t)) {}

	Ret operator[](const Arg &amp;arg)
	{
		return base_-&gt;operator[](arg);
	}

private:
	class base_indexable
	{
	public:
		virtual Ret operator[](const Arg &amp;arg) = 0;	
	};

	template &lt;typename T&gt;
	class basic_indexable : public base_indexable
	{
	public:
		basic_indexable(T &amp;t) noexcept
		: t_(&amp;t) {}

		Ret operator[](const Arg &amp;arg) override
		{
			return (*t_)[arg];
		}

	private:
		T *t_	
	};

	base_indexable *base_:
};
</code></pre>
<p>(Destruktoren fehlen etc.)</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2400940</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2400940</guid><dc:creator><![CDATA[Nathan]]></dc:creator><pubDate>Mon, 26 May 2014 16:32:41 GMT</pubDate></item><item><title><![CDATA[Reply to virtuelles Methoden-Template on Mon, 26 May 2014 16:47:26 GMT]]></title><description><![CDATA[<p>Und für den ersten Fall (Random per Referenz übergeben) würde ich dann auch sowas schreiben? Oder gibt es da eine elegantere Lösung?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2400943</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2400943</guid><dc:creator><![CDATA[Ramanujan]]></dc:creator><pubDate>Mon, 26 May 2014 16:47:26 GMT</pubDate></item><item><title><![CDATA[Reply to virtuelles Methoden-Template on Mon, 26 May 2014 17:44:45 GMT]]></title><description><![CDATA[<p>Ramanujan schrieb:</p>
<blockquote>
<p>Und für den ersten Fall (Random per Referenz übergeben) würde ich dann auch sowas schreiben? Oder gibt es da eine elegantere Lösung?</p>
</blockquote>
<p>Wenn du keine Kopie haben willst, musst du das - AFAIK - selber so machen.<br />
Evtl. kann man da jedoch noch tricksen um das new zu vermeiden.<br />
Warte mal, mir fällt was ein:</p>
<pre><code>class base_function {...};

template &lt;typename Func&gt; class basic_function : ... {...}; // hier dann einen Pointer auf das Funktionsobjekt speichern

template &lt;...&gt; // Funktionssignatur, die gespeichert wird -  oder hardcode fuer das Randomding
class generic_function
{
public:
	generic_function(base_function *fnc) noexcept
	: fnc_(fnc) {}

	// operator()
};

class foo
{
public:
	template &lt;typename Fnc&gt;
	void do_stuff(Fnc &amp;&amp;fnc)
	{
		basic_function&lt;Fnc&gt; basic(forward&lt;Fnc&gt;(fnc));
		impl_do_stuff(&amp;basic);
	}

protected:
	virtual void impl_do_stuff(generic_function fnc)
	{
		...
	}
};
</code></pre>
<p>So haste zumindest kein new mehr.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2400953</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2400953</guid><dc:creator><![CDATA[Nathan]]></dc:creator><pubDate>Mon, 26 May 2014 17:44:45 GMT</pubDate></item><item><title><![CDATA[Reply to virtuelles Methoden-Template on Mon, 26 May 2014 17:50:18 GMT]]></title><description><![CDATA[<blockquote>
<p>Oder gibt es da eine elegantere Lösung?</p>
</blockquote>
<p>Was spricht dagegen <code>std::function</code> zu verwenden und als Konstruktorargument statt dem eigentlichen Funktor einen <code>std::reference_wrapper</code> um den Funktor drum? Damit wären wenigstens die Zeiger raus, die ja bekanntlich in modernem C++ nie in nicht gekapselter Form auftreten.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2400956</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2400956</guid><dc:creator><![CDATA[Columbo]]></dc:creator><pubDate>Mon, 26 May 2014 17:50:18 GMT</pubDate></item><item><title><![CDATA[Reply to virtuelles Methoden-Template on Tue, 27 May 2014 19:21:58 GMT]]></title><description><![CDATA[<pre><code>template&lt; typename T &gt;
struct ref_function : std::function&lt;T&gt;
{
	template&lt; typename F &gt;
	ref_function( F&amp; f ) :
		std::function&lt;T&gt;{ std::ref(f) } {}

	template&lt; typename ... Args &gt;
	ref_function( Args&amp;&amp;... args ) :
		std::function&lt;T&gt;{ std::forward&lt;Args&gt;(args)... } {}
};

.......

virtual void foo( ref_function&lt;std::size_t()&gt; f ) = 0;
</code></pre>
<p><strong>Sollte</strong> ausreichen.</p>
<p>(@Nexus: Ich habe <code>struct</code> missbraucht, aber ich war zu faul um zweimal <code>public</code> zu schreiben.)</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2400962</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2400962</guid><dc:creator><![CDATA[Columbo]]></dc:creator><pubDate>Tue, 27 May 2014 19:21:58 GMT</pubDate></item><item><title><![CDATA[Reply to virtuelles Methoden-Template on Mon, 26 May 2014 18:14:50 GMT]]></title><description><![CDATA[<p>Arcoth schrieb:</p>
<blockquote>
<blockquote>
<p>Oder gibt es da eine elegantere Lösung?</p>
</blockquote>
<p>Was spricht dagegen <code>std::function</code> zu verwenden und als Konstruktorargument statt dem eigentlichen Funktor einen <code>std::reference_wrapper</code> um den Funktor drum? Damit wären wenigstens die Zeiger raus, die ja bekanntlich in modernem C++ nie in nicht gekapselter Form auftreten.</p>
</blockquote>
<p>Falls der Sarkasmus gegen mich war: Das ist ein Fall von Kapselung. Und ich bezog mich auf besitzende Pointer.<br />
Ansonsten guter Ansatz! <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/2400963</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2400963</guid><dc:creator><![CDATA[Nathan]]></dc:creator><pubDate>Mon, 26 May 2014 18:14:50 GMT</pubDate></item><item><title><![CDATA[Reply to virtuelles Methoden-Template on Mon, 26 May 2014 18:15:49 GMT]]></title><description><![CDATA[<blockquote>
<p>Falls der Sarkasmus gegen mich war</p>
</blockquote>
<p>Nein, auf keinen Fall! Der war gegen SeppJ. <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="😃"
    /> <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/2400964</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2400964</guid><dc:creator><![CDATA[Columbo]]></dc:creator><pubDate>Mon, 26 May 2014 18:15:49 GMT</pubDate></item><item><title><![CDATA[Reply to virtuelles Methoden-Template on Tue, 27 May 2014 18:49:21 GMT]]></title><description><![CDATA[<p>@Arcoth<br />
std::reference_wrapper ist gut. Aber wieso so kompliziert?<br />
Wieso nicht einfach</p>
<pre><code class="language-cpp">std::mt19937 rnd;
object.foo(std::ref(rnd));
</code></pre>
<p>?</p>
<p>Oder ist euch das zu &quot;unsicher&quot; - weil man beim Aufruf natürlich auch vergessen kann das <code>std::ref()</code> zu schreiben, und dann nach wie vor eine Kopie des RNG gemacht wird.<br />
Das wäre natürlich ein Argument.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2401140</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2401140</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Tue, 27 May 2014 18:49:21 GMT</pubDate></item><item><title><![CDATA[Reply to virtuelles Methoden-Template on Tue, 27 May 2014 19:29:14 GMT]]></title><description><![CDATA[<blockquote>
<p>Oder ist euch das zu &quot;unsicher&quot; - weil man beim Aufruf natürlich auch vergessen kann das std::ref() zu schreiben, und dann nach wie vor eine Kopie des RNG gemacht wird.</p>
</blockquote>
<p>Genau das.</p>
<p>Edit: Übrigens vielen Dank - ich hatte komischerweise völlig vergessen, dass es <code>std::ref</code> gibt! Habe das obige Beispiel entsprechend angepasst.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2401148</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2401148</guid><dc:creator><![CDATA[Columbo]]></dc:creator><pubDate>Tue, 27 May 2014 19:29:14 GMT</pubDate></item><item><title><![CDATA[Reply to virtuelles Methoden-Template on Wed, 28 May 2014 15:32:11 GMT]]></title><description><![CDATA[<p>Das mit ref_function ist nice und mit std::ref ebenso, aber mir fiel gerade aus, dass ich auf rnd.max() zugreife. Da hat sich das wrappen mit std::function direkt wieder erledigt. Ich denke, dass ich dann wohl einen eigenen Wrapper für Zufallsgeneratoren schreiben müsste.</p>
<p>Fazit:<br />
Templates sind eine schöne Sache. Und Vererbung ebenso. Aber beides zusammen ist furchtbar <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>
]]></description><link>https://www.c-plusplus.net/forum/post/2401256</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2401256</guid><dc:creator><![CDATA[Ramanujan]]></dc:creator><pubDate>Wed, 28 May 2014 15:32:11 GMT</pubDate></item><item><title><![CDATA[Reply to virtuelles Methoden-Template on Wed, 28 May 2014 15:43:25 GMT]]></title><description><![CDATA[<p>Ramanujan schrieb:</p>
<blockquote>
<p>Templates sind eine schöne Sache. Und Vererbung ebenso. Aber beides zusammen ist furchtbar <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>
</blockquote>
<p>Im Gegenteil, mit Type Erasure hast du wahnsinnige Abstraktionsmöglichkeiten. <code>std::function</code> ist ein gutes Beispiel dafür...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2401260</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2401260</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Wed, 28 May 2014 15:43:25 GMT</pubDate></item></channel></rss>