<?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[Delegator: Funktionsargumente, relationale Operatoren]]></title><description><![CDATA[<p>Hallo,</p>
<p>ich implementiere gerade ein Delegator-Template.</p>
<pre><code class="language-cpp">// abstraktes interface für funktoren
template &lt;typename ReturnType&gt;
class Functor
{
	public :
		typedef Core::SmartPtr&lt;Functor&lt;ReturnType&gt; &gt; Ptr;
		virtual ~Functor() { }
		virtual ReturnType operator()() const = 0;
};

// callbacks auf statische funktionen
template &lt;typename ReturnType&gt;
class FunctionBinder : public Functor&lt;ReturnType&gt;
{
	typedef ReturnType(*Callback)();
	public :
		FunctionBinder(Callback cb) : 
			mCallback(cb) 
		{ }		
		ReturnType operator()() const { return mCallback(); }
	private :
		Callback mCallback;
};

// callbacks auf member-funktionen
template &lt;typename Class, typename ReturnType&gt;
class MethodBinder : public Functor&lt;ReturnType&gt;
{
	typedef ReturnType(Class::*Callback)();
	public :	
		MethodBinder(Class *instance, Callback cb) : 
			mInstance(instance), 
			mCallback(cb) 
		{ }		
		ReturnType operator()() const { return (mInstance-&gt;*mCallback)(); }
	private :
		Class *mInstance;
		Callback mCallback;		
};

// der eigentliche delegator
template &lt;typename ReturnType&gt;
class Delegator
{
	typedef ReturnType(*FCallback)();
	public :
		// konstruktor für statische callbacks
		Delegator(FCallback cb)
		{
			mFunctor = new FunctionBinder&lt;ReturnType&gt;(cb);
		}

		// konstruktor für member-callbacks
		template &lt;typename Class&gt;
		Delegator(Class *instance, ReturnType(Class::*cb)())
		{
			mFunctor = new MethodBinder&lt;Class, ReturnType&gt;(instance, cb);
		}

		ReturnType operator()() const
		{
			return (*mFunctor)();
		}
	private :
		typename Functor&lt;ReturnType&gt;::Ptr mFunctor;
};
</code></pre>
<p>Damit kann ich jetzt also Callbacks auf beliebige Funktionen und Methoden binden. Funktioniert soweit problemlos. Nur bei zwei Features weiß ich nicht so recht, wie ich sie implementieren soll.</p>
<p>Zum einen wären das die relationalen Operatoren, zumindest auf Gleichheit müssen sie prüfbar sein. Dabei bedeutet Gleichheit, dass auf die selbe Callback-Funktion gezeigt wird. Da Functor&lt;&gt; aber von Callbacks gar nichts weiß, fehlt mir der Durchblick, wo und wie ich die Operatoren hinzufügen soll.<br />
Ich habe mir überlegt, einen void-Pointer in Functor&lt;&gt; aufzunehmen, dem ich in den Spezialisierungen die Callback-Funktion zuweise. Die könnte ich dann einfach vergleichen. Mein Verständnis von C++ sagt mir aber, dass void-Pointer auf Memberfunktionen alles andere als eindeutig sind.</p>
<p>Der zweite Knackpunkt sind Argumente. Diese Implementierung kann noch keine Argumente an die Callback-Funktionen weitergeben, das habe ich bewusst erst mal außen vor gelassen. Die beste Lösung, die mir bisher eingefallen ist, wären mehrere Kopien aller obigen Templates mit jeweils einem Argument mehr, also</p>
<pre><code class="language-cpp">template &lt;typename ReturnType&gt;
class Functor0
[...]

template &lt;typename ReturnType, typename Arg0&gt;
class Functor1
[...]

template &lt;typename ReturnType, typename Arg0, typename Arg1&gt;
class Functor2
[...]
</code></pre>
<p>...und so weiter, auch für die Spezialisierungen. Variadic Templates wären hier wohl das Richtige, wenn sie denn schon überall verfügbar wären.</p>
<p>Gibt es elegantere Lösungen, die mir nicht eingefallen sind?</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/170740/delegator-funktionsargumente-relationale-operatoren</link><generator>RSS for Node</generator><lastBuildDate>Thu, 17 Sep 2026 04:41:20 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/170740.rss" rel="self" type="application/rss+xml"/><pubDate>Fri, 19 Jan 2007 08:58:30 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Delegator: Funktionsargumente, relationale Operatoren on Fri, 19 Jan 2007 08:58:30 GMT]]></title><description><![CDATA[<p>Hallo,</p>
<p>ich implementiere gerade ein Delegator-Template.</p>
<pre><code class="language-cpp">// abstraktes interface für funktoren
template &lt;typename ReturnType&gt;
class Functor
{
	public :
		typedef Core::SmartPtr&lt;Functor&lt;ReturnType&gt; &gt; Ptr;
		virtual ~Functor() { }
		virtual ReturnType operator()() const = 0;
};

// callbacks auf statische funktionen
template &lt;typename ReturnType&gt;
class FunctionBinder : public Functor&lt;ReturnType&gt;
{
	typedef ReturnType(*Callback)();
	public :
		FunctionBinder(Callback cb) : 
			mCallback(cb) 
		{ }		
		ReturnType operator()() const { return mCallback(); }
	private :
		Callback mCallback;
};

// callbacks auf member-funktionen
template &lt;typename Class, typename ReturnType&gt;
class MethodBinder : public Functor&lt;ReturnType&gt;
{
	typedef ReturnType(Class::*Callback)();
	public :	
		MethodBinder(Class *instance, Callback cb) : 
			mInstance(instance), 
			mCallback(cb) 
		{ }		
		ReturnType operator()() const { return (mInstance-&gt;*mCallback)(); }
	private :
		Class *mInstance;
		Callback mCallback;		
};

// der eigentliche delegator
template &lt;typename ReturnType&gt;
class Delegator
{
	typedef ReturnType(*FCallback)();
	public :
		// konstruktor für statische callbacks
		Delegator(FCallback cb)
		{
			mFunctor = new FunctionBinder&lt;ReturnType&gt;(cb);
		}

		// konstruktor für member-callbacks
		template &lt;typename Class&gt;
		Delegator(Class *instance, ReturnType(Class::*cb)())
		{
			mFunctor = new MethodBinder&lt;Class, ReturnType&gt;(instance, cb);
		}

		ReturnType operator()() const
		{
			return (*mFunctor)();
		}
	private :
		typename Functor&lt;ReturnType&gt;::Ptr mFunctor;
};
</code></pre>
<p>Damit kann ich jetzt also Callbacks auf beliebige Funktionen und Methoden binden. Funktioniert soweit problemlos. Nur bei zwei Features weiß ich nicht so recht, wie ich sie implementieren soll.</p>
<p>Zum einen wären das die relationalen Operatoren, zumindest auf Gleichheit müssen sie prüfbar sein. Dabei bedeutet Gleichheit, dass auf die selbe Callback-Funktion gezeigt wird. Da Functor&lt;&gt; aber von Callbacks gar nichts weiß, fehlt mir der Durchblick, wo und wie ich die Operatoren hinzufügen soll.<br />
Ich habe mir überlegt, einen void-Pointer in Functor&lt;&gt; aufzunehmen, dem ich in den Spezialisierungen die Callback-Funktion zuweise. Die könnte ich dann einfach vergleichen. Mein Verständnis von C++ sagt mir aber, dass void-Pointer auf Memberfunktionen alles andere als eindeutig sind.</p>
<p>Der zweite Knackpunkt sind Argumente. Diese Implementierung kann noch keine Argumente an die Callback-Funktionen weitergeben, das habe ich bewusst erst mal außen vor gelassen. Die beste Lösung, die mir bisher eingefallen ist, wären mehrere Kopien aller obigen Templates mit jeweils einem Argument mehr, also</p>
<pre><code class="language-cpp">template &lt;typename ReturnType&gt;
class Functor0
[...]

template &lt;typename ReturnType, typename Arg0&gt;
class Functor1
[...]

template &lt;typename ReturnType, typename Arg0, typename Arg1&gt;
class Functor2
[...]
</code></pre>
<p>...und so weiter, auch für die Spezialisierungen. Variadic Templates wären hier wohl das Richtige, wenn sie denn schon überall verfügbar wären.</p>
<p>Gibt es elegantere Lösungen, die mir nicht eingefallen sind?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1212464</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1212464</guid><dc:creator><![CDATA[pock]]></dc:creator><pubDate>Fri, 19 Jan 2007 08:58:30 GMT</pubDate></item><item><title><![CDATA[Reply to Delegator: Funktionsargumente, relationale Operatoren on Fri, 19 Jan 2007 09:28:28 GMT]]></title><description><![CDATA[<p>@Vergleiche: Wenn du einen Vergleich einbauen willst, dann vermutlich als virtuelle Methode in den Funktor&lt;&gt;-Klassen:</p>
<pre><code class="language-cpp">//Ausschnitt:
template&lt;typename ret&gt;
class Functor
{
public:
  ...
  virtual bool compare(const Functor&lt;ret&gt;* other)=0;
};

template&lt;typename ret&gt;
class FunctionBinder : public Functor&lt;ret&gt;
{
public:
  ...
  virtual bool compare(const Functor&lt;ret&gt;* other)
  {
    FunctionBinder&lt;ret&gt;* pother = dynamic_cast&lt;FunctionBinder&lt;ret&gt;*&gt;(other);
    //wenn du zwei verschiedene Functor-Klassen vergleichen willst, liefert dynamic_cast&lt;&gt; NULL und damit erhältst du automatisch false
    return (pother!=NULL) &amp;&amp; (pother-&gt;mCallback==this-&gt;mCallback);
  }
};

template&lt;typename ret&gt;
class Delegator
{
public:
  ...
  bool operator==(const Delegator&lt;ret&gt;&amp; other)
  { return mFunctor-&gt;compare(other.mFunctor);}
  bool operator!=(const Delegator&lt;ret&gt;&amp; other)
  { return !mFunctor-&gt;compare(other.mFunctor);}
};
</code></pre>
<p>Zur Übergabe von Argmuneten fällt mir auch nichts ein.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1212483</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1212483</guid><dc:creator><![CDATA[CStoll]]></dc:creator><pubDate>Fri, 19 Jan 2007 09:28:28 GMT</pubDate></item><item><title><![CDATA[Reply to Delegator: Funktionsargumente, relationale Operatoren on Fri, 19 Jan 2007 09:55:46 GMT]]></title><description><![CDATA[<p>Das funktioniert prinzipiell mal, danke. Ich sollte wohl meine Casting-Paranoia etwas runterfahren, damit mir sowas selbst einfällt <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>
<p>Problematisch ist nur, dass ich auf RTTI verzichten möchte und dynamic_cast deshalb nicht in Frage kommt. Es lässt sich aber auch mit static_cast implementieren, wenn ich mich um die Typsicherheit selbst kümmere.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1212499</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1212499</guid><dc:creator><![CDATA[pock]]></dc:creator><pubDate>Fri, 19 Jan 2007 09:55:46 GMT</pubDate></item><item><title><![CDATA[Reply to Delegator: Funktionsargumente, relationale Operatoren on Fri, 19 Jan 2007 10:12:20 GMT]]></title><description><![CDATA[<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/14451">@pock</a><br />
Schau dir einfach mal Loki::Functor (<a href="http://loki-lib.sourceforge.net/" rel="nofollow">http://loki-lib.sourceforge.net/</a>) bzw. boost::function (<a href="http://www.boost.org/doc/html/function.html" rel="nofollow">http://www.boost.org/doc/html/function.html</a>) an, da findest du jeweils Ansätze für die Unterstützung von Argumenten. Letztlich läuft jeder Ansatz auf Code-Duplikation hinaus.</p>
<p>Btw: Dein Ansatz funktioniert zwar, ist aber nicht sonderlich effizient (vorallem was Code-Größe angeht). Falls es sich nicht nur um ein Lernprojekt handelt, würde ich dir zu einer fertigen Lib raten. boost::function ist sehr mächtig und ausgereift. Loki::Functor ist dafür etwas performanter. <a href="http://www.codeproject.com/cpp/FastDelegate.asp" rel="nofollow">FastDelegate</a> ist auf Geschwindigkeit optimiert, dafür aber weder hübsch noch wirklich portabel.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1212507</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1212507</guid><dc:creator><![CDATA[HumeSikkins]]></dc:creator><pubDate>Fri, 19 Jan 2007 10:12:20 GMT</pubDate></item><item><title><![CDATA[Reply to Delegator: Funktionsargumente, relationale Operatoren on Fri, 19 Jan 2007 10:08:30 GMT]]></title><description><![CDATA[<p>pock schrieb:</p>
<blockquote>
<p>Problematisch ist nur, dass ich auf RTTI verzichten möchte und dynamic_cast deshalb nicht in Frage kommt. Es lässt sich aber auch mit static_cast implementieren, wenn ich mich um die Typsicherheit selbst kümmere.</p>
</blockquote>
<p>Du arbeitest mit virtuellen Methoden - und dann willst du auf RTTI verzichten? Wozu soll das etwas bringen?</p>
<p>(wenn du auf dynamic_cast verzichten willst, mußt du wirklich diese Typ-Überprüfung selber durchführen:</p>
<pre><code class="language-cpp">bool FunctionBinder&lt;ret&gt;::compare(const Functor&lt;ret&gt;* other)
{
  //gettype() ist eine virtuelle Methode, die eine je nach Typ eindeutigen ID liefert
  return (other-&gt;gettype()==ID_FUNC)&amp;&amp;(static_cast&lt;FunctionBinder&lt;ret&gt;*&gt;(other)-&gt;mFunctor==this-&gt;mFunctor);
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1212510</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1212510</guid><dc:creator><![CDATA[CStoll]]></dc:creator><pubDate>Fri, 19 Jan 2007 10:08:30 GMT</pubDate></item><item><title><![CDATA[Reply to Delegator: Funktionsargumente, relationale Operatoren on Fri, 19 Jan 2007 10:52:08 GMT]]></title><description><![CDATA[<p>Danke für die Tipps.</p>
<p>RTTI möchte ich deshalb nicht nutzen, weil es meiner Meinung nach schlechten Programmierstil fördert. Es mag Projekte geben, die den Einsatz von RTTI rechtfertigen, aber generell denke ich dass Typinformationen zur Laufzeit eher schädlich als nützlich sind und zu abenteuerlichen Konstruktionen führen können. Wenn man einen Hammer hat, sieht alles nach Nagel aus. Zudem soll der Code von Leuten genutzt werden, die nicht unbedingt C++-Kenner sind. Denen will ich lieber mal so wenig Möglichkeiten wie möglich bieten, sich in den Fuß zu schießen. Wenn die RTTI wollen, bitte. Dann ist es aber ihr Problem.</p>
<p>Abhängigkeiten zu Dritt-Bibliotheken will und muss ich so gering wie möglich halten, deshalb kein boost etc. Als Inspirationsquelle natürlich gern.<br />
Ob mein Ansatz für den geplanten Einsatzzweck effizient genug ist, muss sich noch rausstellen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1212550</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1212550</guid><dc:creator><![CDATA[pock]]></dc:creator><pubDate>Fri, 19 Jan 2007 10:52:08 GMT</pubDate></item><item><title><![CDATA[Reply to Delegator: Funktionsargumente, relationale Operatoren on Fri, 19 Jan 2007 10:59:54 GMT]]></title><description><![CDATA[<p>pock schrieb:</p>
<blockquote>
<p>RTTI möchte ich deshalb nicht nutzen, weil es meiner Meinung nach schlechten Programmierstil fördert. Es mag Projekte geben, die den Einsatz von RTTI rechtfertigen, aber generell denke ich dass Typinformationen zur Laufzeit eher schädlich als nützlich sind und zu abenteuerlichen Konstruktionen führen können. Wenn man einen Hammer hat, sieht alles nach Nagel aus. Zudem soll der Code von Leuten genutzt werden, die nicht unbedingt C++-Kenner sind. Denen will ich lieber mal so wenig Möglichkeiten wie möglich bieten, sich in den Fuß zu schießen. Wenn die RTTI wollen, bitte. Dann ist es aber ihr Problem.</p>
</blockquote>
<p>Für so jemanden ist aber dynamic_cast bestimmt sicherer als jeder Versuch, RTTI von Hand nachzuahmen. Die einzige Alternative zu dynamic_cast&lt;&gt; und der dc-Imitation über gettype()+static-cast wäre vermutlich Double Dispatching, aber das ist wahrscheinlich noch komplexer.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1212556</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1212556</guid><dc:creator><![CDATA[CStoll]]></dc:creator><pubDate>Fri, 19 Jan 2007 10:59:54 GMT</pubDate></item></channel></rss>