<?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[Template zum Methodenaufruf]]></title><description><![CDATA[<p>Hallo,</p>
<p>ich wollte mal fragen, ob es irgendeine Möglichkeit gibt, ein Aufruftemplate zu schreiben, dem man einen Klassentyp und eine Methode des Klassentyps mitgeben kann, sodass dieses Template genau diese Methode der Klasse aufruft, wenn man ihm noch einen Objektzeiger und die entsprechenden Argumente übergibt.</p>
<p>Also Pseudocodemäßig folgendes:</p>
<pre><code class="language-cpp">template&lt; typename Class, ??? Func &gt;
struct caller {
    template&lt; typename Arg1 &gt;
    void call( Class* obj, Arg1&amp; arg )
    {
        obj-&gt;Func( arg );
    };
};

class some {
public:
  func( int Arg1 );
};

some a;
caller&lt;some,some::func&gt;::call( &amp;a, 5 );
</code></pre>
<p>Das würde ich verwenden wollen für die Tag-Geschichte, mit der ich mich gerade anfreunde. Speziell möchte ich für Tags eine gesonderte Klasse default_tag verwenden, welche bedeutet, dass die aufgerufene Methode keinen Tag benötigt, weil der Name eindeutig ist. Allerdings fällt mir im Moment kein Weg ein, wie man das ohne spezialisierte Duplizierung des Methodenaufrufs hinbekommt (oder mit Methodenzeigern, aber das ganze ist ja eigentlich statisch bestimmt, daher möchte ich diese nicht verwenden).</p>
<p>Viele Grüße,<br />
Deci</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/311767/template-zum-methodenaufruf</link><generator>RSS for Node</generator><lastBuildDate>Mon, 03 Aug 2026 09:39:11 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/311767.rss" rel="self" type="application/rss+xml"/><pubDate>Fri, 14 Dec 2012 08:43:26 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Template zum Methodenaufruf on Fri, 14 Dec 2012 08:46:04 GMT]]></title><description><![CDATA[<p>Hallo,</p>
<p>ich wollte mal fragen, ob es irgendeine Möglichkeit gibt, ein Aufruftemplate zu schreiben, dem man einen Klassentyp und eine Methode des Klassentyps mitgeben kann, sodass dieses Template genau diese Methode der Klasse aufruft, wenn man ihm noch einen Objektzeiger und die entsprechenden Argumente übergibt.</p>
<p>Also Pseudocodemäßig folgendes:</p>
<pre><code class="language-cpp">template&lt; typename Class, ??? Func &gt;
struct caller {
    template&lt; typename Arg1 &gt;
    void call( Class* obj, Arg1&amp; arg )
    {
        obj-&gt;Func( arg );
    };
};

class some {
public:
  func( int Arg1 );
};

some a;
caller&lt;some,some::func&gt;::call( &amp;a, 5 );
</code></pre>
<p>Das würde ich verwenden wollen für die Tag-Geschichte, mit der ich mich gerade anfreunde. Speziell möchte ich für Tags eine gesonderte Klasse default_tag verwenden, welche bedeutet, dass die aufgerufene Methode keinen Tag benötigt, weil der Name eindeutig ist. Allerdings fällt mir im Moment kein Weg ein, wie man das ohne spezialisierte Duplizierung des Methodenaufrufs hinbekommt (oder mit Methodenzeigern, aber das ganze ist ja eigentlich statisch bestimmt, daher möchte ich diese nicht verwenden).</p>
<p>Viele Grüße,<br />
Deci</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2280003</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2280003</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Fri, 14 Dec 2012 08:46:04 GMT</pubDate></item><item><title><![CDATA[Reply to Template zum Methodenaufruf on Fri, 14 Dec 2012 08:59:34 GMT]]></title><description><![CDATA[<p>Arg!</p>
<p>Das funktioniert wirklich:</p>
<pre><code class="language-cpp">template&lt; typename Class, typename Tag &gt;
struct caller {
	template&lt; typename Arg1, void (Class::*Func)( Arg1 ) &gt;
	static void call( Class* c, Arg1 arg1 ) {
		(c-&gt;*Func)( arg1 );
	}
};
</code></pre>
<p>Entschuldigt, irgendwie hatte ich im Gedächtnis, dass ich das früher schonmal erfolglos versucht habe. <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/2280010</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2280010</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Fri, 14 Dec 2012 08:59:34 GMT</pubDate></item><item><title><![CDATA[Reply to Template zum Methodenaufruf on Fri, 14 Dec 2012 09:01:45 GMT]]></title><description><![CDATA[<p>Nur ueber Umwege.</p>
<pre><code>template &lt;typename...&gt;
struct pack;

template &lt;typename Class, typename R, typename Args&gt;
struct caller;

template &lt;typename Class, typename R, typename... P, R (Class::* Ptr) (P...)&gt;
struct caller&lt;Class, R, pack&lt;P...&gt;, Ptr&gt;
{
    template &lt;typename... Args&gt;
    R call(Class* obj, Args&amp;&amp;... args)
    {
        return (obj-&gt;*Ptr)(std::forward&lt;Args&gt;(args)...);
    }
};
</code></pre>
<p>Ungetestet.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2280011</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2280011</guid><dc:creator><![CDATA[Kellerautomat]]></dc:creator><pubDate>Fri, 14 Dec 2012 09:01:45 GMT</pubDate></item><item><title><![CDATA[Reply to Template zum Methodenaufruf on Fri, 14 Dec 2012 09:06:45 GMT]]></title><description><![CDATA[<p>Ja danke Dir für Deine Zeit! Ich schaue mit einem weinenden Auge auf die Variadic templates, die ich nicht zur Verfügung habe <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/2280013</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2280013</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Fri, 14 Dec 2012 09:06:45 GMT</pubDate></item><item><title><![CDATA[Reply to Template zum Methodenaufruf on Fri, 14 Dec 2012 19:49:49 GMT]]></title><description><![CDATA[<p>Hrmmm, also bei mir funktioniert das so nicht, wie Du das angezeigt hast, weil die Template-Spezialisierung eben mehr Parameter hat als das Template.<br />
Jetzt ist auch das Problem, dass man bei nicht-typ-Parametern ja schon den richtigen Typ im unspezialisierten Template angeben muss. Wenn ich erst die statische wrapper-Funktion auf den Funktionszeiger templatisiere, dann kann ich dort nicht mehr die Argumente deduzieren lassen, sodass die unified-references für die gegebenen Argumente fehlen und das perfect forwarding deshalb nicht klappt -.-</p>
<p>Hier im Moment der einzige Ansatz, den ich bislang lauffähig bekommen habe:</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
using std::wcout;

struct default_tag {};

// 0 Arguments
template&lt; typename Class, typename Tag = default_tag &gt;
struct tag_call0
{
    template&lt; typename Ret, Ret (Class::*FuncPtr)( Tag ) &gt;
    struct intern {
        static Ret call( Class* object ) {
            return (object-&gt;*FuncPtr)( Tag() );
        }
    };
};

template&lt; typename Class &gt;
struct tag_call0&lt; Class, default_tag &gt;
{
    template&lt; typename Ret, Ret (Class::*FuncPtr)() &gt;
    struct intern {
        static Ret call( Class* object ) {
            return (object-&gt;*FuncPtr)();
        }
    };
};

// 1 Arguments
template&lt; typename Class, typename Tag = default_tag &gt;
struct tag_call1
{
    template&lt; typename Ret, typename A1, Ret (Class::*FuncPtr)( A1, Tag ) &gt;
    struct intern {
		template&lt; typename Arg1 &gt;
        static Ret call( Class* object, Arg1&amp;&amp; arg1 ) {
            return (object-&gt;*FuncPtr)( std::forward&lt;Arg1&gt;(arg1), Tag() );
        }
    };
};

template&lt; typename Class &gt;
struct tag_call1&lt; Class, default_tag &gt;
{
    template&lt; typename Ret, typename A1, Ret (Class::*FuncPtr)( A1 ) &gt;
    struct intern {
		template&lt; typename Arg1 &gt;
        static Ret call( Class* object, Arg1&amp;&amp; arg1 ) {
            return (object-&gt;*FuncPtr)( std::forward&lt;Arg1&gt;(arg1) );
        }
    };
};

struct tag {};

class some {
public:
	int func1() {  wcout &lt;&lt; L&quot;Called non-tagged method #1.\n&quot;; return 1; }
	int func1( tag ) { wcout &lt;&lt; L&quot;Called tagged method #1.\n&quot;; return 1; }

	int func2( float ) {  wcout &lt;&lt; L&quot;Called non-tagged method #2.\n&quot;; return 1; }
	int func2( float, tag ) { wcout &lt;&lt; L&quot;Called tagged method #2.\n&quot;; return 1; }

};

int main()
{
    some a;
    tag_call0&lt; some, tag         &gt;::intern&lt; int, &amp;some::func1 &gt;::call( &amp;a );
	tag_call0&lt; some, default_tag &gt;::intern&lt; int, &amp;some::func1 &gt;::call( &amp;a );

	tag_call1&lt; some, tag         &gt;::intern&lt; int, float, &amp;some::func2 &gt;::call( &amp;a, 4.0f );
	tag_call1&lt; some, default_tag &gt;::intern&lt; int, float, &amp;some::func2 &gt;::call( &amp;a, 4.0f );
}
</code></pre>
<p>Was ich mir noch funktionierend vorstellen könnte wäre soetwas wie:</p>
<pre><code class="language-cpp">tag_call&lt; some, tag, decltype(&amp;some::func) &gt;::intern&lt; &amp;some_func &gt;::call( &amp;a );
</code></pre>
<p>Dann müsste man wenigstens nichtmehr die Argumente und Return-Types angeben, also könnte ein einziges äußeres template für alle Methoden mit 0-n Argumenten verwenden, muss dafür aber zweimal die Funktion angeben -.-</p>
<p>EDIT: Das mit dem decltype funktioniert so natürlich auch nicht, wenn die Funktion überladen ist, also muss man auch dort den vollen Prototypen angeben. Und das funktioniert natürlich nicht, weil man da den tag-dekorierten Typ schon braucht und das template soll ja den Aufruf erst mit dem Tag dekorieren, falls kein default_tag angegeben war. -.-</p>
<p>Sehe ich hier den Wald vor lauter Bäumen nicht mehr?</p>
<p>Viele Grüße,<br />
Deci</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2280177</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2280177</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Fri, 14 Dec 2012 19:49:49 GMT</pubDate></item><item><title><![CDATA[Reply to Template zum Methodenaufruf on Fri, 14 Dec 2012 20:32:27 GMT]]></title><description><![CDATA[<p>Also für die zweite Option fällt mir nur ein, dass man sich noch weitere Hilfs-Templates baut, die den Methodenprototypen zerpflücken und mit der Tag-Information vermengen und dann einen neuen Prototypen daraus basteln. Das ist mir die Sache eher nicht wert...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2280204</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2280204</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Fri, 14 Dec 2012 20:32:27 GMT</pubDate></item><item><title><![CDATA[Reply to Template zum Methodenaufruf on Sat, 15 Dec 2012 02:23:09 GMT]]></title><description><![CDATA[<p>Hilf dir das ein wenig?</p>
<pre><code>#include &lt;iostream&gt;
using namespace std;

struct tag {}; 
struct default_tag {}; 

class some 
{
	public:

    	int func1() {  wcout &lt;&lt; L&quot;Called non-tagged method #1.\n&quot;; return 1; } 
    	int func1( tag ) { wcout &lt;&lt; L&quot;Called tagged method #1.\n&quot;; return 1; } 

    	int func2( float ) {  wcout &lt;&lt; L&quot;Called non-tagged method #2.\n&quot;; return 1; } 
    	int func2( float, tag ) { wcout &lt;&lt; L&quot;Called tagged method #2.\n&quot;; return 1; } 

}; 

template&lt;bool Tagged&gt;
struct Caller;

template&lt;&gt;
struct Caller&lt;true&gt;
{
	template&lt;typename Class, typename FunPtrTyp&gt;
	static int call(Class&amp; obj, FunPtrTyp funPtr)
	{
		return (obj.*funPtr)(tag());
	}
};

template&lt;&gt;
struct Caller&lt;false&gt;
{
	template&lt;typename Class, typename FunPtrTyp&gt;
	static int call(Class&amp; obj, FunPtrTyp funPtr)
	{
		return (obj.*funPtr)();
	}
};

template&lt;typename Class, typename Tag, typename ReturnType&gt;
struct caller_0
{
	typedef ReturnType (Class::*DefaultFunPtr)();
	typedef ReturnType (Class::*TaggedFunPtr)(tag);

	static const bool is_tagged = is_same&lt;Tag, tag&gt;::value;  
	typedef typename conditional&lt;is_tagged, TaggedFunPtr, DefaultFunPtr&gt;::type FunPtrTyp;	

	static ReturnType call(Class&amp; obj, FunPtrTyp funPtr)
	{
		return Caller&lt;is_tagged&gt;::call(obj, funPtr);
	}

};

template&lt;typename Tag, typename Class, typename ReturnType&gt;
ReturnType callMe(Class a, ReturnType (Class::*fun)())
{
	// Edit: Ups, geht ja noch einfacher:
    return caller_0&lt;Class, Tag, ReturnType&gt;::call(a, &amp;Class::func1);

    //return caller_0&lt;Class, Tag, decltype((((Class*)nullptr)-&gt;*fun)())&gt;::call(a, &amp;Class::func1);
}

int main()
{
	some a;	

	callMe&lt;tag&gt;(a, &amp;some::func1);
	callMe&lt;default_tag&gt;(a, &amp;some::func1);
}
</code></pre>
<p>Ich glaub ohne variadic templates oder Ellipsen, kommst du nicht bequem so einfach dran vorbei mehrere Argumente zu übergeben.</p>
<p>Edit: Ich sehe gerade nen Fehler in Zeile 64. &amp;Class::func1 ... Naja, jetzt ist es schon zu spät.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2280249</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2280249</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Sat, 15 Dec 2012 02:23:09 GMT</pubDate></item></channel></rss>