<?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[Als Zeiger designter Proxy - Implementierung]]></title><description><![CDATA[<p>Hi,</p>
<p>ich habe mir jetzt Mal einen Proxy gebastelt, der sich wie ein Zeiger verhält. D.h. man kann über operator-&gt; die Funktionen aufrufen und über operator= das Bezugsobjekt ändern. const-correctness klappt auch sowohl auf Ebene des Proxys als auch auf Ebene der eigentlichen Klasse. Proxy als Zeiger impliziert natürlich, dass es sich um einen Proxy handelt, bei dem das eigentliche Objekt bereits irgendwo im Speicher besteht und der Proxy nur darauf verweist, nicht aber besitzend ist. Kann man sich drüber streiten, ob man das so will, ich finde es praktisch.</p>
<p>operator* habe ich mir hingegen gespart, weil mein Proxy nicht ausgetrickst können werden soll. Wenn jemand einen Proxy erhält, dann muss er auch über die Methoden gehen, die er kriegt, und soll es nicht umgehen können.</p>
<p>Ich habe es noch etwas abstrahiert: Man kann mit beliebigen Proxyimplementierungen für alle möglichen Klassen Proxys mit oben genannten Eigenschaften generieren (der Schritt ist möglicherweise nicht besonders hilfreich, ist aber praktisch, wenn man noch Operatoren hinzufügen möchte oder so).</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;type_traits&gt;

// ===================================================
// Proxybasis: Kann zur Erzeugung unterschiedlicher Proxys verwendet werden

template&lt;typename ProxyImpl&gt; 
class ProxyBase 
{ 
	typedef typename ProxyImpl::type ActualClass;

	ProxyImpl proxyImpl;

public: 
	ProxyBase(ActualClass&amp; someClass) : proxyImpl(someClass) {} 

	// Proxyobjekt durch Zuweisung veränderbar
	ProxyBase&lt;ProxyImpl&gt;&amp; operator=(ActualClass* someClass)
	{
		proxyImpl.someClass = someClass;
		return *this;
	}

    // const_cast ist hier sauber, da alle non-const Methoden ohnehin nicht funktionieren, wenn ProxyImpl::type const ist;
    // und es ist notwendig, weil ein const Proxy die Semantik hat, dass man über -&gt; das Objekt verändern darf
	ProxyImpl* operator-&gt;() const {return const_cast&lt;ProxyImpl*&gt;(&amp;proxyImpl);}
};

// ===================================================
// Anwendung der Proxybasis zur Proxyerzeugung

// Eigentliche Klasse
class SomeClass
{
public:
	void foo() {std::cout &lt;&lt; &quot;foo\n&quot;;}
	void bar() const {std::cout &lt;&lt; &quot;bar\n&quot;;}
} sc;

// Implementierung des Proxys; muss type definieren und ctor haben, der type akzeptiert
template&lt;typename T&gt;
struct SomeClassProxyImpl 
{ 
	typedef T type;

	type* someClass; 
	SomeClassProxyImpl(type&amp; someClass) : someClass(&amp;someClass) {} 

	void foo() {someClass-&gt;foo();} 
	void bar() const {someClass-&gt;bar();} 
};

// jetzt geht: 
typedef ProxyBase&lt;SomeClassProxyImpl&lt;const SomeClass&gt;&gt; ConstSomeClassProxy; 
typedef ProxyBase&lt;SomeClassProxyImpl&lt;SomeClass&gt;&gt; SomeClassProxy; 

// und auch die vier Varianten 
const ConstSomeClassProxy proxy1(sc); // Bezugsobjekt nicht austauschbar, nicht änderbar 
ConstSomeClassProxy proxy2(sc); // Bezugsobjekt austauschbar, nicht änderbar 
const SomeClassProxy proxy3(sc); // Bezugsobjekt nicht austauschbar, doch änderbar 
SomeClassProxy proxy4(sc); // Bezugsobjekt austauschbar, und änderbar

int main()
{
	// Proxy1
	//proxy1 = &amp;sc; // geht nicht
	//proxy1-&gt;foo(); // geht nicht
	proxy1-&gt;bar();

	// Proxy 2
	proxy2 = &amp;sc;
	//proxy2-&gt;foo(); // geht nicht
	proxy2-&gt;bar();

	// Proxy 3
	//proxy3 = &amp;sc; // geht nicht
	proxy3-&gt;foo();
	proxy3-&gt;bar();

	// Proxy 4
	proxy4 = &amp;sc;
	proxy4-&gt;foo();
	proxy4-&gt;bar();

	int x; std::cin &gt;&gt; x;
}
</code></pre>
<p>Kurz an dieser späten Stelle zur Motivation fürs Zeigerverhalten:<br />
Ich kann jetzt z.B. das hier tun:</p>
<pre><code class="language-cpp">template&lt;typename PointerType&gt;
void doSomething(PointerType p) {p-&gt;foo();}

// mit:
doSomething(&amp;sc);
// oder:
doSomething(proxy4);
</code></pre>
<p>und das freut mich. <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="🙂"
    /> Somit kann ich jetzt endlich austauschbar Zeiger auf Objekte und Proxys auf Objekte nutzen - wenn auch nur auf Compiletime-Basis.</p>
<p>Habt ihr Verbesserungsvorschläge oder sonstige Anmerkungen?</p>
<p>Vielen Dank und viele Grüße!</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/319603/als-zeiger-designter-proxy-implementierung</link><generator>RSS for Node</generator><lastBuildDate>Sat, 25 Jul 2026 03:06:56 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/319603.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 25 Aug 2013 14:21:45 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Als Zeiger designter Proxy - Implementierung on Mon, 26 Aug 2013 11:54:10 GMT]]></title><description><![CDATA[<p>Hi,</p>
<p>ich habe mir jetzt Mal einen Proxy gebastelt, der sich wie ein Zeiger verhält. D.h. man kann über operator-&gt; die Funktionen aufrufen und über operator= das Bezugsobjekt ändern. const-correctness klappt auch sowohl auf Ebene des Proxys als auch auf Ebene der eigentlichen Klasse. Proxy als Zeiger impliziert natürlich, dass es sich um einen Proxy handelt, bei dem das eigentliche Objekt bereits irgendwo im Speicher besteht und der Proxy nur darauf verweist, nicht aber besitzend ist. Kann man sich drüber streiten, ob man das so will, ich finde es praktisch.</p>
<p>operator* habe ich mir hingegen gespart, weil mein Proxy nicht ausgetrickst können werden soll. Wenn jemand einen Proxy erhält, dann muss er auch über die Methoden gehen, die er kriegt, und soll es nicht umgehen können.</p>
<p>Ich habe es noch etwas abstrahiert: Man kann mit beliebigen Proxyimplementierungen für alle möglichen Klassen Proxys mit oben genannten Eigenschaften generieren (der Schritt ist möglicherweise nicht besonders hilfreich, ist aber praktisch, wenn man noch Operatoren hinzufügen möchte oder so).</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;type_traits&gt;

// ===================================================
// Proxybasis: Kann zur Erzeugung unterschiedlicher Proxys verwendet werden

template&lt;typename ProxyImpl&gt; 
class ProxyBase 
{ 
	typedef typename ProxyImpl::type ActualClass;

	ProxyImpl proxyImpl;

public: 
	ProxyBase(ActualClass&amp; someClass) : proxyImpl(someClass) {} 

	// Proxyobjekt durch Zuweisung veränderbar
	ProxyBase&lt;ProxyImpl&gt;&amp; operator=(ActualClass* someClass)
	{
		proxyImpl.someClass = someClass;
		return *this;
	}

    // const_cast ist hier sauber, da alle non-const Methoden ohnehin nicht funktionieren, wenn ProxyImpl::type const ist;
    // und es ist notwendig, weil ein const Proxy die Semantik hat, dass man über -&gt; das Objekt verändern darf
	ProxyImpl* operator-&gt;() const {return const_cast&lt;ProxyImpl*&gt;(&amp;proxyImpl);}
};

// ===================================================
// Anwendung der Proxybasis zur Proxyerzeugung

// Eigentliche Klasse
class SomeClass
{
public:
	void foo() {std::cout &lt;&lt; &quot;foo\n&quot;;}
	void bar() const {std::cout &lt;&lt; &quot;bar\n&quot;;}
} sc;

// Implementierung des Proxys; muss type definieren und ctor haben, der type akzeptiert
template&lt;typename T&gt;
struct SomeClassProxyImpl 
{ 
	typedef T type;

	type* someClass; 
	SomeClassProxyImpl(type&amp; someClass) : someClass(&amp;someClass) {} 

	void foo() {someClass-&gt;foo();} 
	void bar() const {someClass-&gt;bar();} 
};

// jetzt geht: 
typedef ProxyBase&lt;SomeClassProxyImpl&lt;const SomeClass&gt;&gt; ConstSomeClassProxy; 
typedef ProxyBase&lt;SomeClassProxyImpl&lt;SomeClass&gt;&gt; SomeClassProxy; 

// und auch die vier Varianten 
const ConstSomeClassProxy proxy1(sc); // Bezugsobjekt nicht austauschbar, nicht änderbar 
ConstSomeClassProxy proxy2(sc); // Bezugsobjekt austauschbar, nicht änderbar 
const SomeClassProxy proxy3(sc); // Bezugsobjekt nicht austauschbar, doch änderbar 
SomeClassProxy proxy4(sc); // Bezugsobjekt austauschbar, und änderbar

int main()
{
	// Proxy1
	//proxy1 = &amp;sc; // geht nicht
	//proxy1-&gt;foo(); // geht nicht
	proxy1-&gt;bar();

	// Proxy 2
	proxy2 = &amp;sc;
	//proxy2-&gt;foo(); // geht nicht
	proxy2-&gt;bar();

	// Proxy 3
	//proxy3 = &amp;sc; // geht nicht
	proxy3-&gt;foo();
	proxy3-&gt;bar();

	// Proxy 4
	proxy4 = &amp;sc;
	proxy4-&gt;foo();
	proxy4-&gt;bar();

	int x; std::cin &gt;&gt; x;
}
</code></pre>
<p>Kurz an dieser späten Stelle zur Motivation fürs Zeigerverhalten:<br />
Ich kann jetzt z.B. das hier tun:</p>
<pre><code class="language-cpp">template&lt;typename PointerType&gt;
void doSomething(PointerType p) {p-&gt;foo();}

// mit:
doSomething(&amp;sc);
// oder:
doSomething(proxy4);
</code></pre>
<p>und das freut mich. <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="🙂"
    /> Somit kann ich jetzt endlich austauschbar Zeiger auf Objekte und Proxys auf Objekte nutzen - wenn auch nur auf Compiletime-Basis.</p>
<p>Habt ihr Verbesserungsvorschläge oder sonstige Anmerkungen?</p>
<p>Vielen Dank und viele Grüße!</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2348435</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2348435</guid><dc:creator><![CDATA[Eisflamme]]></dc:creator><pubDate>Mon, 26 Aug 2013 11:54:10 GMT</pubDate></item><item><title><![CDATA[Reply to Als Zeiger designter Proxy - Implementierung on Mon, 26 Aug 2013 08:47:29 GMT]]></title><description><![CDATA[<p>Das kompiliert mit MSVC10, aber wieso meckert Ideone in Zeile 44:<br />
<code>expected nested-name-specifier before T</code><br />
?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2348534</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2348534</guid><dc:creator><![CDATA[Eisflamme]]></dc:creator><pubDate>Mon, 26 Aug 2013 08:47:29 GMT</pubDate></item><item><title><![CDATA[Reply to Als Zeiger designter Proxy - Implementierung on Mon, 26 Aug 2013 08:49:42 GMT]]></title><description><![CDATA[<p>Weil es falsch ist, MSVC nun mal aber jeden Scheiß schluckt.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2348536</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2348536</guid><dc:creator><![CDATA[Sone]]></dc:creator><pubDate>Mon, 26 Aug 2013 08:49:42 GMT</pubDate></item><item><title><![CDATA[Reply to Als Zeiger designter Proxy - Implementierung on Mon, 26 Aug 2013 08:53:17 GMT]]></title><description><![CDATA[<p>Und wie geht es richtig? <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>
]]></description><link>https://www.c-plusplus.net/forum/post/2348538</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2348538</guid><dc:creator><![CDATA[Eisflamme]]></dc:creator><pubDate>Mon, 26 Aug 2013 08:53:17 GMT</pubDate></item><item><title><![CDATA[Reply to Als Zeiger designter Proxy - Implementierung on Mon, 26 Aug 2013 09:00:54 GMT]]></title><description><![CDATA[<p>Eisflamme schrieb:</p>
<blockquote>
<p>Und wie geht es richtig? <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>
</blockquote>
<p>Ohne <code>typename</code> .</p>
<blockquote>
<p>typename-speciﬁer:<br />
typename nested-name-speciﬁer identiﬁer<br />
typename nested-name-speciﬁer [template] simple-template-id</p>
</blockquote>
<p>Den benutzt man nicht ohne <em>nested-name-speciﬁer</em>.</p>
<pre><code>struct A
{
	using int_ = int;
};

int main()
{
	typename A::int_ i;

	typename A a; // Compilerfehler
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2348540</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2348540</guid><dc:creator><![CDATA[Sone]]></dc:creator><pubDate>Mon, 26 Aug 2013 09:00:54 GMT</pubDate></item><item><title><![CDATA[Reply to Als Zeiger designter Proxy - Implementierung on Mon, 26 Aug 2013 09:07:26 GMT]]></title><description><![CDATA[<p>Ah okay, dankesehr.</p>
<p>Gäbe es denn eine Möglichkeit hier überhaupt einen nested-name specifier anzugeben? T ist ja nicht im global namespace und auf den Template-Space schaffe ich es nicht ohne Weiteres zuzugreifen.</p>
<p>Das hier scheint nicht zu gehen:</p>
<pre><code class="language-cpp">typedef typename SomeClassProxyImpl&lt;T&gt;::T type;
</code></pre>
<p>Jedoch funktioniert:</p>
<pre><code class="language-cpp">typedef T type1;
typedef typename SomeClassProxyImpl&lt;T&gt;::type1 type2; // sorry, hier stand Müll vorher
</code></pre>
<p>Leider muss ich mit dem alten Compiler arbeiten, using steht mir da ja nicht zur Verfügung. <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/2348542</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2348542</guid><dc:creator><![CDATA[Eisflamme]]></dc:creator><pubDate>Mon, 26 Aug 2013 09:07:26 GMT</pubDate></item><item><title><![CDATA[Reply to Als Zeiger designter Proxy - Implementierung on Mon, 26 Aug 2013 09:14:02 GMT]]></title><description><![CDATA[<p>Eisflamme schrieb:</p>
<blockquote>
<p>Gäbe es denn eine Möglichkeit hier überhaupt einen nested-name specifier anzugeben?</p>
</blockquote>
<p>Nein, aber das brauchst du auch nicht. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f615.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--confused_face"
      title=":confused:"
      alt="😕"
    /></p>
<blockquote>
<p>Das hier scheint nicht zu gehen:</p>
<pre><code class="language-cpp">typedef typename SomeClassProxyImpl&lt;T&gt;::T type;
</code></pre>
</blockquote>
<p>Natürlich nicht, T ist schließlich kein Member dieser Klasse.</p>
<blockquote>
<p>Leider muss ich mit dem alten Compiler arbeiten, using steht mir da ja nicht zur Verfügung. <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>
</blockquote>
<p>alias-Deklarationen sind nur Syntaxzucker, die sind nicht irgendwie anders als typedef.</p>
<blockquote>
<p>A typedef-name can also be introduced by an alias-declaration. [...] It has the same semantics as if it were introduced by the typedef specifier.</p>
</blockquote>
<p>_________________________________________________________________________________</p>
<blockquote>
<pre><code>typedef T type1; 
typedef typename SomeClassProxyImpl&lt;T&gt;::type1 type2; // sorry, hier stand Müll vorher
</code></pre>
</blockquote>
<p>...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2348544</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2348544</guid><dc:creator><![CDATA[Sone]]></dc:creator><pubDate>Mon, 26 Aug 2013 09:14:02 GMT</pubDate></item><item><title><![CDATA[Reply to Als Zeiger designter Proxy - Implementierung on Mon, 26 Aug 2013 09:20:16 GMT]]></title><description><![CDATA[<p>Ja, war auch eher eine Interessensfrage. Aber ich merke, dass MSVC da Käse macht. Schade, dann muss man ja ständig noch mit nem Zweitcompiler testen, ob der Code auch wirklich standardkonform ist (oder es einfach wissen).</p>
<p>Edit:<br />
Die zweite Variante habe ich gewählt, weil ich im Kopf hatte, dass MSVC dann bei späterer Verwendung von type2 für nested types kein typename mehr erforderte. Ergibt zwar keinen Sinn, aber ich meine gesehen zu haben, dass:</p>
<pre><code class="language-cpp">typedef typename T type;
</code></pre>
<p>dazu führt, dass</p>
<pre><code class="language-cpp">typedef /* typename weg! */ type::nested_type;
</code></pre>
<p>klappt, was Schreibarbeit erspart, wenn man viele nested_types typedefen will.</p>
<p>Ergibt keinen Sinn, wenn man drüber nachdenkt, hatte aber meine ich Mal funktioniert, aber vielleicht habe ich das auch verwechselt. Jedenfalls bin ich erstmal belehrt. Danke <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>
]]></description><link>https://www.c-plusplus.net/forum/post/2348549</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2348549</guid><dc:creator><![CDATA[Eisflamme]]></dc:creator><pubDate>Mon, 26 Aug 2013 09:20:16 GMT</pubDate></item></channel></rss>