<?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[Signatur Klassen template]]></title><description><![CDATA[<p>Hi zusammen,</p>
<p>mir fällt grad kein passender Titel ein, wie ich das Problem nennen soll. Prinzipiell habe ich eine Variable in einer Klasse gekapselt, auf die policy-gesteuert zugegriffen werden kann. Es gibt zwei Policies: direkt ohne Zugriffsschutz und SynchronizedAccess mit einem Synchronisierungsobjekt, das den Zugriff aus mehreren Thread gleichzeitig verhindert.</p>
<pre><code class="language-c++">template&lt;typename T&gt;
struct immediate_access
{
   // direkter Zugriff ohne Synchroniserung: Wert darf als const-ref zurückgegeben werden
   using return_type = T const&amp;;

   immediate_access() = default;

   return_type  value( T const&amp; v ) const
   {
      return v;
   }

   void lock()
   {
   }

   void unlock()
   {
   }
};

template&lt;typename T&gt;
struct synchronized_access
{
   // in Multithreading-Umgebungen muss der Wert als Kopie zurückgegeben werden, außerdem wird ein Objekt für die Synchroniserung gebraucht.
   using return_type = T;
   sync_object Lock_;
   
   synchronized_access() = default;

   return_type  value( T const&amp; value ) const
   {
      return value;
   }

   void lock()
   {
      Lock_.lock();   
   }

   void unlock()
   {
      Lock_.unlock();   
   }
};

// Default: Direkter Zugriff ohne Synchronisierung
template&lt;typename T, typename accessor = immediate_access&lt;T&gt;&gt;
class observable : public lockable
{
   using value_type           = T;
   using const_reference      = T const&amp;;
   using accessor_return_type = typename accessor::return_type;

   value_type   Value_;
   accessor     Accessor_;

public:
   publisher    OnChange; // Pseudo Code für Callback-Handler

public:
   observable() = default;

   accessor_return_type value() const
   {
      // RAII scoped Lock-Klasse, Zugriff wird über die Lebenszeit des lock-Objekts gesperrt
      scoped_lock const lock( *this );
      return Accessor_.value( Value_ );      
   }

   void set_value( const_reference val )
   {
      auto update = [&amp;]()
      {
         scoped_lock const lock( *this );
         if( Value_ != val )
         {
            Value_ = val;
            return true;
         }
         return false;
      };
      if( update() )
      {
         // Subscriber über Wertänderung informieren
         OnChange( *this );
      }
   }

private:
   void lock()
   {
      Accessor_.lock();
   }

   void unlock()
   {
      Accessor_.unlock();
   }
};
</code></pre>
<p>In der Anwendung soll das dann so aussehen:</p>
<pre><code class="language-c++">struct test
{
   observable&lt;int&gt; o1; // Direkter Zugriff ohne Synchronisierung (default template Parameter ist immediate_access)
   observable&lt;int,synchronized_access&lt;int&gt;&gt; o2; // thread safe Zugriff durch synchroniserten Zugriff
 
   test()
   {
      o1.OnChange.connect( *this, &amp;test::on_change );
      o2.OnChange.connect( *this, &amp;test::on_change ); // &lt;&lt; Problem, Signatur passt nicht
   }

   void on_change( observable&lt;int&gt; const&amp; var )
   {
      ...
   }
};
</code></pre>
<p>Das Problem tritt in Zeile 9 auf, weil <code>observable&lt;int&gt;</code> und <code>observable&lt;int, synchronized_access&lt;int&gt;&gt;</code> unterschiedliche Typen sind. Gibt's da irgendeine schlaue Idee, wie ich den zweiten Template-Parameter verstecken kann? Ich könnte natürlich von einer Basisklasse ableiten, aber da hätte ich dann das Problem, dass der Rückgabewert der <code>value()</code> Funktion von der policy-Klasse abhängt und es schwierig macht, durch die Basisklasse an den Wert zu kommen.<br />
Oder bin ich hier generell schwer auf dem Holzweg und lauf in eine Sackgasse?</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/354266/signatur-klassen-template</link><generator>RSS for Node</generator><lastBuildDate>Fri, 13 Mar 2026 17:42:44 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/354266.rss" rel="self" type="application/rss+xml"/><pubDate>Thu, 24 Aug 2023 09:02:26 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Signatur Klassen template on Thu, 24 Aug 2023 09:09:06 GMT]]></title><description><![CDATA[<p>Hi zusammen,</p>
<p>mir fällt grad kein passender Titel ein, wie ich das Problem nennen soll. Prinzipiell habe ich eine Variable in einer Klasse gekapselt, auf die policy-gesteuert zugegriffen werden kann. Es gibt zwei Policies: direkt ohne Zugriffsschutz und SynchronizedAccess mit einem Synchronisierungsobjekt, das den Zugriff aus mehreren Thread gleichzeitig verhindert.</p>
<pre><code class="language-c++">template&lt;typename T&gt;
struct immediate_access
{
   // direkter Zugriff ohne Synchroniserung: Wert darf als const-ref zurückgegeben werden
   using return_type = T const&amp;;

   immediate_access() = default;

   return_type  value( T const&amp; v ) const
   {
      return v;
   }

   void lock()
   {
   }

   void unlock()
   {
   }
};

template&lt;typename T&gt;
struct synchronized_access
{
   // in Multithreading-Umgebungen muss der Wert als Kopie zurückgegeben werden, außerdem wird ein Objekt für die Synchroniserung gebraucht.
   using return_type = T;
   sync_object Lock_;
   
   synchronized_access() = default;

   return_type  value( T const&amp; value ) const
   {
      return value;
   }

   void lock()
   {
      Lock_.lock();   
   }

   void unlock()
   {
      Lock_.unlock();   
   }
};

// Default: Direkter Zugriff ohne Synchronisierung
template&lt;typename T, typename accessor = immediate_access&lt;T&gt;&gt;
class observable : public lockable
{
   using value_type           = T;
   using const_reference      = T const&amp;;
   using accessor_return_type = typename accessor::return_type;

   value_type   Value_;
   accessor     Accessor_;

public:
   publisher    OnChange; // Pseudo Code für Callback-Handler

public:
   observable() = default;

   accessor_return_type value() const
   {
      // RAII scoped Lock-Klasse, Zugriff wird über die Lebenszeit des lock-Objekts gesperrt
      scoped_lock const lock( *this );
      return Accessor_.value( Value_ );      
   }

   void set_value( const_reference val )
   {
      auto update = [&amp;]()
      {
         scoped_lock const lock( *this );
         if( Value_ != val )
         {
            Value_ = val;
            return true;
         }
         return false;
      };
      if( update() )
      {
         // Subscriber über Wertänderung informieren
         OnChange( *this );
      }
   }

private:
   void lock()
   {
      Accessor_.lock();
   }

   void unlock()
   {
      Accessor_.unlock();
   }
};
</code></pre>
<p>In der Anwendung soll das dann so aussehen:</p>
<pre><code class="language-c++">struct test
{
   observable&lt;int&gt; o1; // Direkter Zugriff ohne Synchronisierung (default template Parameter ist immediate_access)
   observable&lt;int,synchronized_access&lt;int&gt;&gt; o2; // thread safe Zugriff durch synchroniserten Zugriff
 
   test()
   {
      o1.OnChange.connect( *this, &amp;test::on_change );
      o2.OnChange.connect( *this, &amp;test::on_change ); // &lt;&lt; Problem, Signatur passt nicht
   }

   void on_change( observable&lt;int&gt; const&amp; var )
   {
      ...
   }
};
</code></pre>
<p>Das Problem tritt in Zeile 9 auf, weil <code>observable&lt;int&gt;</code> und <code>observable&lt;int, synchronized_access&lt;int&gt;&gt;</code> unterschiedliche Typen sind. Gibt's da irgendeine schlaue Idee, wie ich den zweiten Template-Parameter verstecken kann? Ich könnte natürlich von einer Basisklasse ableiten, aber da hätte ich dann das Problem, dass der Rückgabewert der <code>value()</code> Funktion von der policy-Klasse abhängt und es schwierig macht, durch die Basisklasse an den Wert zu kommen.<br />
Oder bin ich hier generell schwer auf dem Holzweg und lauf in eine Sackgasse?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2617659</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2617659</guid><dc:creator><![CDATA[DocShoe]]></dc:creator><pubDate>Thu, 24 Aug 2023 09:09:06 GMT</pubDate></item><item><title><![CDATA[Reply to Signatur Klassen template on Thu, 24 Aug 2023 11:26:13 GMT]]></title><description><![CDATA[<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/18927">@DocShoe</a> Ich würde es hier vielleicht mit einem Concept versuchen, das einen Typ-Parameter hat, mit dem geprüft wird, ob der Typ ein <code>observable&lt;T&gt;</code> mit einem beliebigen zweiten Template-Parameter ist.</p>
<p>Das Concept könnte das entweder dadurch prüfen, dass die Klasseninstanzen entweder durch eine gemeinsame Basisklasse &quot;markiert&quot; sind, oder ob sie ein bestimmtes Interface implementieren (z.B. hat <code>value</code> und <code>set_value</code>, Member-Funktionen, <code>value</code> gibt ein <code>T::accessor_return_type</code> zurück, etc.).</p>
<p>Dann könnte <code>on_change</code> so aussehen:</p>
<pre><code class="language-cpp">void on_change( observable_concept&lt;int&gt; const&amp; auto var )
</code></pre>
<p>Letztendlich ist das nur die &quot;coole&quot; Variante von:</p>
<pre><code class="language-cpp">template &lt;typename T&gt;
void on_change( T const&amp; var )
</code></pre>
<p>Holzweg oder Sackgasse wird sich vermutlich erst im weiteren Code und in der Anwendung zeigen. Man wird den vollen Typen immer auf die eine oder andere Art mitführen und durchreichen müssen, wenn man da nicht irgendwo eine Type Erasure z.B. mit polymorphen Klassen zwischenschiebt.</p>
<p><code>std::vector&lt;int, custom_allocator&lt;int&gt;&gt;</code> wäre da ein Beispiel aus der Standardbibliothek, bei dem ich vermute, dass du eventuell irgendwann auf ähnlich gelagerte Probleme treffen könntest. Mit so einem Design kann man schon eine Menge machen, aber es hat auch seine Gründe, weshalb es Ansätze wie <code>std::pmr::polymorphic_allocator</code> gibt.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2617660</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2617660</guid><dc:creator><![CDATA[Finnegan]]></dc:creator><pubDate>Thu, 24 Aug 2023 11:26:13 GMT</pubDate></item><item><title><![CDATA[Reply to Signatur Klassen template on Thu, 24 Aug 2023 11:33:00 GMT]]></title><description><![CDATA[<p>Finnegan hat es schon beschrieben. Es bliebe noch anzumerken falls es beim zweiten Parametern bleibt, sollte dieser zu einem Template Template Parameter geändert werden.</p>
<p>Dann braucht man nicht <code>observable&lt;int, synchronized_access&lt;int&gt;&gt;</code>schreiben, sondern kann das auf <code>observable&lt;int, synchronized_access&gt;</code> kürzen.</p>
<p>Dazu braucht man dann</p>
<pre><code class="language-cpp">template&lt;typename T, template&lt;typename = T&gt; typename accessor = immediate_access&gt;
class observable : public lockable
…
</code></pre>
<p>als neue Template Definition.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2617662</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2617662</guid><dc:creator><![CDATA[*john 0]]></dc:creator><pubDate>Thu, 24 Aug 2023 11:33:00 GMT</pubDate></item><item><title><![CDATA[Reply to Signatur Klassen template on Thu, 24 Aug 2023 11:40:25 GMT]]></title><description><![CDATA[<p>Danke für eure Antworten<br />
<a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/31711">@Finnegan</a> Ich bin auf C++17 beschränkt und kann keine Concepts benutzen</p>
<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/16792">@john-0</a><br />
Danke für die Info, die Umstellung auf einen template template Paramter habe ich schon, aber die Benutzung von <code>T</code>als Default Template Parameter kannte ich noch nicht.</p>
<p>Edit:<br />
Wenn's halt nicht anders geht, dann ist das halt so. Der Benutzer muss ja schließlich auch den Objekttypen vollständig qualifizieren, dann muss er das in seinen Callback halt auch tun. Vermutlich ist das auch nur eine hypothetische Frage, wäre halt schön gewesen, wenn man für alle oberservable Typen einen einzigen Callback registrieren könnte.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2617663</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2617663</guid><dc:creator><![CDATA[DocShoe]]></dc:creator><pubDate>Thu, 24 Aug 2023 11:40:25 GMT</pubDate></item><item><title><![CDATA[Reply to Signatur Klassen template on Thu, 24 Aug 2023 13:34:48 GMT]]></title><description><![CDATA[<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/18927">@DocShoe</a> sagte in <a href="/forum/post/2617663">Signatur Klassen template</a>:</p>
<blockquote>
<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/16792">@john-0</a><br />
Danke für die Info, die Umstellung auf einen template template Paramter habe ich schon, aber die Benutzung von <code>T</code>als Default Template Parameter kannte ich noch nicht.</p>
</blockquote>
<p>Man muss leider relativ lange suchen, bis man die korrekte Formulierung findet. Auch in dem an für sich sehr guten Buch von Josuttis und Vandevoorde <em>C++ Templates</em> steht das nicht drin. <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/2617667</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2617667</guid><dc:creator><![CDATA[*john 0]]></dc:creator><pubDate>Thu, 24 Aug 2023 13:34:48 GMT</pubDate></item></channel></rss>