<?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[Matrix&#x2F;Vektorklasse]]></title><description><![CDATA[<p>Guten Abend,</p>
<p>ich bearbeite gerade meine alten Matrix/Vektorklassen, die ich mir für ein Spiel geschrieben hatte. Momentant sind das noch zwei verschiedene Klassen, ich bin mir allerdings nicht ganz sicher, ob ich sie noch &quot;vereine&quot;. (Das gehört aber eigentlich nicht zur Frage.)<br />
Also meine Matrixklasse sieht in etwa so aus:</p>
<pre><code class="language-cpp">template&lt;typename T, unsigned N&gt;
  struct BlockMatrix
  {
    // ...
  private:
    T data_[N][N];
  public:
    // ...
    // Bitte keine Hinweise auf size_t statt unsigned. ;)
    T* operator [] (unsigned index)
    {
      return data_[index];
    }
    T const* operator [] (unsigned index) const
    {
      return data_[index];
    }
    // ...
  };
</code></pre>
<p>Ich gebe hier also T* bei operator [] zurück, was mir so nicht gefällt. Eine Referenz auf einen Vektor zurückzugeben würde ich wesentlich angenehmer finden. Allerdings muss die Matrix eine .data() Methode haben, die auf sicher zusammenhängenden Speicher zeigt. (Um sie in einen Shader zu kopieren.)<br />
Das bedeutet, dass ich nicht einfach einen GeometricVector&lt;T, N&gt; vectors_[N] verwenden kann, was natürlich perfekt wäre. (Nervt mich eh extrem, dass der Standard kein Mittel zur Paddingkontrolle gibt. -.-)<br />
Ich könnte natürlich eine Vektorklasse schreiben, die einfach einen Pointer auf ihren Speicherbereich erhält. Wenn ich das dann allerdings zurückgeben würde (value), würde das komisches Verhalten nach sich ziehen:</p>
<pre><code class="language-cpp">auto v = matrix[0];
v.x() = 5; // Verändert Matrix, obwohl v keine Referenz ist.
           // So ein Verhalten ist aber natürlich völlig undurchsichtig.
</code></pre>
<p>operator [] muss also definitiv eine Referenz auf irgendetwas zurückgeben. Wenn ich also zusätzlich zu T[N][N] noch ein Array aus N Vektoren definiere, die jeweils einen Teil des Speichers &quot;verwalten&quot;, und auf die ich dann Referenzen liefern kann, stellt sich ein neues Problem. Wie initialisiere ich die? Da die Größe nicht bekannt ist, kann man die Initialisierungsliste vergessen. Ok, also in einer Schleife im Konstruktor. Trotzdem, operator = ist ja schon besetzt, der macht eine tiefe Kopie. Also vielleicht über eine &quot;setMemory()&quot; Methode? Ja, das könnte wohl gehen, aber irgendwie scheint mir das Ganze mehr und mehr zusammengefrickelt, und ich wollte mal hören, ob hier jemand eine bessere Idee dazu hat.</p>
<p>Besten Dank im Voraus. <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>Edit: Mittlerweile bin ich fast gewillt, den operator [] ganz wegzulassen und nur einen operator (i, j) anzubieten.</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/298499/matrix-vektorklasse</link><generator>RSS for Node</generator><lastBuildDate>Thu, 13 Aug 2026 19:50:58 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/298499.rss" rel="self" type="application/rss+xml"/><pubDate>Sat, 21 Jan 2012 17:05:09 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Matrix&#x2F;Vektorklasse on Sat, 21 Jan 2012 18:03:21 GMT]]></title><description><![CDATA[<p>Guten Abend,</p>
<p>ich bearbeite gerade meine alten Matrix/Vektorklassen, die ich mir für ein Spiel geschrieben hatte. Momentant sind das noch zwei verschiedene Klassen, ich bin mir allerdings nicht ganz sicher, ob ich sie noch &quot;vereine&quot;. (Das gehört aber eigentlich nicht zur Frage.)<br />
Also meine Matrixklasse sieht in etwa so aus:</p>
<pre><code class="language-cpp">template&lt;typename T, unsigned N&gt;
  struct BlockMatrix
  {
    // ...
  private:
    T data_[N][N];
  public:
    // ...
    // Bitte keine Hinweise auf size_t statt unsigned. ;)
    T* operator [] (unsigned index)
    {
      return data_[index];
    }
    T const* operator [] (unsigned index) const
    {
      return data_[index];
    }
    // ...
  };
</code></pre>
<p>Ich gebe hier also T* bei operator [] zurück, was mir so nicht gefällt. Eine Referenz auf einen Vektor zurückzugeben würde ich wesentlich angenehmer finden. Allerdings muss die Matrix eine .data() Methode haben, die auf sicher zusammenhängenden Speicher zeigt. (Um sie in einen Shader zu kopieren.)<br />
Das bedeutet, dass ich nicht einfach einen GeometricVector&lt;T, N&gt; vectors_[N] verwenden kann, was natürlich perfekt wäre. (Nervt mich eh extrem, dass der Standard kein Mittel zur Paddingkontrolle gibt. -.-)<br />
Ich könnte natürlich eine Vektorklasse schreiben, die einfach einen Pointer auf ihren Speicherbereich erhält. Wenn ich das dann allerdings zurückgeben würde (value), würde das komisches Verhalten nach sich ziehen:</p>
<pre><code class="language-cpp">auto v = matrix[0];
v.x() = 5; // Verändert Matrix, obwohl v keine Referenz ist.
           // So ein Verhalten ist aber natürlich völlig undurchsichtig.
</code></pre>
<p>operator [] muss also definitiv eine Referenz auf irgendetwas zurückgeben. Wenn ich also zusätzlich zu T[N][N] noch ein Array aus N Vektoren definiere, die jeweils einen Teil des Speichers &quot;verwalten&quot;, und auf die ich dann Referenzen liefern kann, stellt sich ein neues Problem. Wie initialisiere ich die? Da die Größe nicht bekannt ist, kann man die Initialisierungsliste vergessen. Ok, also in einer Schleife im Konstruktor. Trotzdem, operator = ist ja schon besetzt, der macht eine tiefe Kopie. Also vielleicht über eine &quot;setMemory()&quot; Methode? Ja, das könnte wohl gehen, aber irgendwie scheint mir das Ganze mehr und mehr zusammengefrickelt, und ich wollte mal hören, ob hier jemand eine bessere Idee dazu hat.</p>
<p>Besten Dank im Voraus. <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>Edit: Mittlerweile bin ich fast gewillt, den operator [] ganz wegzulassen und nur einen operator (i, j) anzubieten.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2170854</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2170854</guid><dc:creator><![CDATA[cooky451]]></dc:creator><pubDate>Sat, 21 Jan 2012 18:03:21 GMT</pubDate></item><item><title><![CDATA[Reply to Matrix&#x2F;Vektorklasse on Sat, 21 Jan 2012 19:51:16 GMT]]></title><description><![CDATA[<p>Dank Pis völliger Schnapsidee versuche ich mich gerade an reinterpret_cast&lt;&gt;. <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="😃"
    /><br />
Soweit ich mich erinnern kann, ist hier</p>
<pre><code class="language-cpp">struct A { int i; };
</code></pre>
<p>garantiert, dass gilt: (&amp;A == &amp;A.i).<br />
Da die Vektorklasse ja auch nur einen Member hat, sollte so ein Cast also eigentlich möglich sein:<br />
<a href="http://ideone.com/luBe4" rel="nofollow">http://ideone.com/luBe4</a></p>
<pre><code class="language-cpp">#include &lt;iostream&gt;

struct V
{
  char foo[5];
  V()
  {}
  char&amp; operator [] (unsigned index)
  {
    return foo[index];
  }
  void print()
  {
    std::cout &lt;&lt; foo[2] &lt;&lt; '\n';
  }
};

struct A
{
  char foo[5][5];
  V&amp; operator [] (unsigned index)
  {
    return reinterpret_cast&lt;V&amp;&gt;(foo[index]);
  }
};

int main()
{
  A a;
  a[2][2] = 'L';
  a[2].print();
}
</code></pre>
<p>Ich frage mich jetzt nur, ob dieser Cast auch von POD nach nicht POD definiert ist?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2170914</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2170914</guid><dc:creator><![CDATA[cooky451]]></dc:creator><pubDate>Sat, 21 Jan 2012 19:51:16 GMT</pubDate></item><item><title><![CDATA[Reply to Matrix&#x2F;Vektorklasse on Sat, 21 Jan 2012 20:22:30 GMT]]></title><description><![CDATA[<p>cooky451 schrieb:</p>
<blockquote>
<p>Edit: Mittlerweile bin ich fast gewillt, den operator [] ganz wegzulassen und nur einen operator (i, j) anzubieten.</p>
</blockquote>
<p>Warum baust du dir keinen Proxy, der den operator(i,j) aufruft?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2170926</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2170926</guid><dc:creator><![CDATA[proxyschroxy]]></dc:creator><pubDate>Sat, 21 Jan 2012 20:22:30 GMT</pubDate></item><item><title><![CDATA[Reply to Matrix&#x2F;Vektorklasse on Sat, 21 Jan 2012 20:30:53 GMT]]></title><description><![CDATA[<p>Ein löbliches Ziel, wie ich finde. Ich sehe nur keine vernünftige Lösung. Dass &quot;auto&quot; mit Vorsicht zu genießen ist, viel mir schon auf, als ich mich mit Expression Templates beschäftigt habe.</p>
<p>Der C++ Standard macht es nicht besser:</p>
<pre><code class="language-cpp">vector&lt;bool&gt; foo;
foo.push_back(false);
auto x = foo.front();
x = true;
cout &lt;&lt; foo.front() &lt;&lt; endl;
</code></pre>
<p><a href="http://ideone.com/luHK0" rel="nofollow">http://ideone.com/luHK0</a></p>
<p>Ich habe schon öfters mal darüber nachgedacht, ob bei so einer Stelle &quot;operator auto&quot; nicht ganz praktisch sein könnte:</p>
<pre><code class="language-cpp">class bool_ref
{
  vector&lt;bool&gt;&amp; vec;
  int index;
public:
  …
  bool_ref&amp; operator=(bool b) const { vec[index] = b; return *this; }

  bool operator auto() const { return vec[index]; }
  …
};

…

  auto x = …bool_ref-Ausdruck…;
  decltype(x) --&gt; bool
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2170929</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2170929</guid><dc:creator><![CDATA[krümelkacker]]></dc:creator><pubDate>Sat, 21 Jan 2012 20:30:53 GMT</pubDate></item><item><title><![CDATA[Reply to Matrix&#x2F;Vektorklasse on Sat, 21 Jan 2012 21:14:39 GMT]]></title><description><![CDATA[<p>Ich bin der reinterpret_cast-Lösung momentan wirklich zugeneigt. Funktioniert zumindest mit VS und GCC, und ich kann nur vermuten, dass das Verhalten sogar garantiert ist.<br />
Die Iteratoren der Matrix habe ich auch von T(<em>)[N] auf T</em> geändert. Fragt sich eigentlich nur noch, ob es sich lohnt der Matrixklasse zwei einzelne Dimensionen zu spendieren und die Vektorklasse aufzulösen. Allerdings müsste man bei Vektoren dann v[0][1] statt v[1] schreiben, andererseits schreibe ich für Vector2, Vector3 und Vector4 eh extra Klassen, bei denen man auch mit .x(), .y(), .. auf die Elemente zugreifen kann. Schwere Entscheidung. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f921.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--clown_face"
      title=":clown:"
      alt="🤡"
    /><br />
Aber ich glaube mit reinterpret_cast immerhin für das operator [] Problem eine nette Lösung gefunden zu haben.<br />
Wenn der Kram fertig ist poste ich ihn mal hier, mathematisch wohl eher uninteressant aber vielleicht freut es ja ein paar Spieleleute.</p>
<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/24868">@krümelkacker</a><br />
Ein Grund mehr vector&lt;bool&gt; zu meiden. <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/2170941</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2170941</guid><dc:creator><![CDATA[cooky451]]></dc:creator><pubDate>Sat, 21 Jan 2012 21:14:39 GMT</pubDate></item><item><title><![CDATA[Reply to Matrix&#x2F;Vektorklasse on Sat, 21 Jan 2012 21:24:20 GMT]]></title><description><![CDATA[<p>cooky451 schrieb:</p>
<blockquote>
<p>Eine Referenz auf einen Vektor zurückzugeben würde ich wesentlich angenehmer finden.</p>
</blockquote>
<p>Wäre bei</p>
<pre><code class="language-cpp">std::array&lt; GeometricVector&lt;T, N&gt;, N &gt;
</code></pre>
<p>das einzige Problem, dass <code>GeometricVector&lt;T, N&gt;</code> durch Padding grösser als <code>N * sizeof(T)</code> sein könnte, selbst wenn du intern ein Array <code>T[N]</code> verwenden würdest?</p>
<p>krümelkacker schrieb:</p>
<blockquote>
<p>Ich habe schon öfters mal darüber nachgedacht, ob bei so einer Stelle &quot;operator auto&quot; nicht ganz praktisch sein könnte</p>
</blockquote>
<p>Sowas könnte man vielleicht auch durch Traits bewerkstelligen:</p>
<pre><code class="language-cpp">template &lt;typename T&gt;
struct unproxified_type
{
    typedef T type;
};

template &lt;&gt;
struct unproxified_type&lt; std::vector&lt;bool&gt;::reference &gt;
{
	typedef bool type;
};

template &lt;typename T&gt;
typename unproxified_type&lt;T&gt;::type unproxify(T expr)
{
    return expr;
};

#define AUTO(var, expr) auto x = unproxify(expr)
</code></pre>
<p>Vielleicht noch mit <code>std::forward</code> . Gibt es eigentlich bereits eine Metafunktion, die einen Typen gleich r/lvalue-qualifiziert wie einen anderen?</p>
<pre><code class="language-cpp">metafn&lt;double, int&gt;::type        == double
metafn&lt;double, int&amp;&amp;&gt;::type      == double&amp;&amp;
metafn&lt;double, const int&amp;&gt;::type == const double&amp;
</code></pre>
<p>Das <code>AUTO</code> -Makro ist zwar nicht so hübsch wie die Zuweisung und muss dem Anwender bekannt sein, aber <code>operator auto</code> kommt mir ehrlich gesagt auch etwas speziell vor <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2170945</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2170945</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Sat, 21 Jan 2012 21:24:20 GMT</pubDate></item><item><title><![CDATA[Reply to Matrix&#x2F;Vektorklasse on Sat, 21 Jan 2012 21:27:03 GMT]]></title><description><![CDATA[<p>Ein static_assert(sizeof(Vector&lt;T, N&gt;)==sizeof(T[N])) ist trotzdem erforderlich, um Padding am Ende zu umgehen. Andernfalls wird dir<br />
Matrix[0]=Matrix[1];<br />
Probleme bereiten.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2170949</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2170949</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Sat, 21 Jan 2012 21:27:03 GMT</pubDate></item><item><title><![CDATA[Reply to Matrix&#x2F;Vektorklasse on Sat, 21 Jan 2012 21:35:59 GMT]]></title><description><![CDATA[<p>Nexus schrieb:</p>
<blockquote>
<p>Wäre bei</p>
<pre><code class="language-cpp">std::array&lt; GeometricVector&lt;T, N&gt;, N &gt;
</code></pre>
<p>das einzige Problem, dass <code>GeometricVector&lt;T, N&gt;</code> durch Padding grösser als <code>N * sizeof(T)</code> sein könnte, selbst wenn du intern ein Array <code>T[N]</code> verwenden würdest?</p>
</blockquote>
<p>Jop.</p>
<p>camper schrieb:</p>
<blockquote>
<p>Andernfalls wird dir<br />
Matrix[0]=Matrix[1];</p>
</blockquote>
<p>Sicher? Der operator = ist ja manuell geschrieben, oder darf da im Hintergrund noch mehr kopiert werden? (Ich denke mal du beziehst dich darauf, dass dann mehr kopiert werden könnte?)</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2170952</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2170952</guid><dc:creator><![CDATA[cooky451]]></dc:creator><pubDate>Sat, 21 Jan 2012 21:35:59 GMT</pubDate></item></channel></rss>