<?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[templates und pointer-to-member-function in verteilten Quelldateien]]></title><description><![CDATA[<p><em>Die Beispiele sind natürlich bewusst einfach konstruiert und drum sinnfrei!</em></p>
<p>Nehmen wir an, wir hätten ein algebraisches Konstrukt definiert, sagen wir einmal eine Ebene. Da wäre es doch schön, wenn dieselbe für mehrere Datentypen funktionieren würde, fixed-point Ganzzahlen, double, vielleicht auch für Exotischeres.<br />
Da bietet es sich wohl an, das Ding als template zu definieren, mit dem numerischen Datentyp als Parameter.</p>
<p>Nun kommt man vielleicht in die Verlegenheit, dass man zwar weiß, wie oft eine Methode einer Klasse ausgeführt werden soll - aber nicht welche. Na, da lässt man sich eben einfach sagen, welche es denn sein soll, per Parameter.</p>
<p>Kombiniert man nun diese beiden Lösungen, will man also einen Zeiger auf die Methode einer template-Ebene herumreichen, so trifft man - zumindest bei minGW (G++ 4.7.0) - auf folgendes Kuriosum:</p>
<p>Ist die Ebene in der selben Quelldatei definiert, funktioniert's - ist sie das aber nicht, findet der Linker die angegebenen Methoden nicht.<br />
Definierte man die Ebene nun nicht als template - funktioniert es wiederum.</p>
<p>Was wäre zu tun, um dieses Unbill zu beseitigen, mit anderen Worten: seine allgemeine Ebene andernortes zu definieren ohne deshalb nicht mehr ihre Methoden zeigerhaft herumreichen zu können?</p>
<pre><code>#include &lt;iostream&gt;
#include &lt;valarray&gt;

using namespace std;

template &lt;typename T&gt; class Ebene
{
  protected:
    valarray&lt;T&gt; fusspunkt;
    valarray&lt;T&gt; normalenvektor;

  public:
    Ebene() : fusspunkt(), normalenvektor() {}
    Ebene(const valarray&lt;T&gt; &amp; neuerFusspunkt) : fusspunkt(neuerFusspunkt), normalenvektor() {}
    Ebene(const valarray&lt;T&gt; &amp; neuerFusspunkt, const valarray&lt;T&gt; &amp; neuerNormalenvektor) : fusspunkt(neuerFusspunkt), normalenvektor(neuerNormalenvektor) {}
    Ebene(const Ebene&lt;T&gt; &amp; ebene) : fusspunkt(ebene.fusspunkt), normalenvektor(ebene.normalenvektor) {}

    bool istOberhalb (const valarray&lt;T&gt; &amp; punkt) // Punkt liegt in Richtung des Normalenvektors              oder in der Ebene
    {
      return 0. &gt;= (this-&gt;normalenvektor * (this-&gt;fusspunkt - punkt)).sum();
    }
    bool istUnterhalb(const valarray&lt;T&gt; &amp; punkt) // Punkt liegt in Richtung des invertierten Normalenvektors oder in der Ebene
    {
      return 0. &lt;= (this-&gt;normalenvektor * (this-&gt;fusspunkt - punkt)).sum();
    }
};

bool punktLiegtGut(Ebene&lt;double&gt; &amp; ebene, const valarray&lt;double&gt; &amp; punkt, bool (Ebene&lt;double&gt;::* oberOderUnterhalb)(const valarray&lt;double&gt; &amp; punkt))
{
  return (ebene.*oberOderUnterhalb)(punkt);
}

int main ()
{
  valarray&lt;double&gt; normale(3);
  valarray&lt;double&gt; fuss(3);
  valarray&lt;double&gt; punkt(3);
  for(unsigned int z = 0; z &lt; 3; z++)
  {
    normale[z] = (double) z;
    fuss[z]    = (double)-z;
    punkt[z]   = (double)(z * (z % 2) - z * ((z + 1) % 2));
  }

  Ebene&lt;double&gt; e(fuss, normale);
  cout &lt;&lt; punktLiegtGut(e, punkt, &amp;Ebene&lt;double&gt;::istOberhalb) &lt;&lt; endl;
  cout &lt;&lt; punktLiegtGut(e, punkt, &amp;Ebene&lt;double&gt;::istUnterhalb) &lt;&lt; endl;

  return 0;
}
</code></pre>
<pre><code>/************/
/* main.cpp */
/************/

#include &lt;iostream&gt;
#include &lt;valarray&gt;

#include &quot;Include.h&quot;

using namespace std;

bool punktLiegtGut(Ebene&lt;double&gt; &amp; ebene, const valarray&lt;double&gt; &amp; punkt, bool (Ebene&lt;double&gt;::* oberOderUnterhalb)(const valarray&lt;double&gt; &amp; punkt))
{
  return (ebene.*oberOderUnterhalb)(punkt);
}

int main ()
{
  valarray&lt;double&gt; normale(3);
  valarray&lt;double&gt; fuss(3);
  valarray&lt;double&gt; punkt(3);
  for(unsigned int z = 0; z &lt; 3; z++)
  {
    normale[z] = (double) z;
    fuss[z]    = (double)-z;
    punkt[z]   = (double)(z * (z % 2) - z * ((z + 1) % 2));
  }

  Ebene&lt;double&gt; e(fuss, normale);
  cout &lt;&lt; punktLiegtGut(e, punkt, &amp;Ebene&lt;double&gt;::istOberhalb) &lt;&lt; endl;
  cout &lt;&lt; punktLiegtGut(e, punkt, &amp;Ebene&lt;double&gt;::istUnterhalb) &lt;&lt; endl;

  return 0;
}

/*************/
/* Include.h */
/*************/

#ifndef INCLUDE_H
#define INCLUDE_H

#include &lt;valarray&gt;

using namespace std;

template &lt;typename T&gt; class Ebene
{
  protected:
    valarray&lt;T&gt; fusspunkt;
    valarray&lt;T&gt; normalenvektor;

  public:
    Ebene();
    Ebene(const valarray&lt;T&gt; &amp; neuerFusspunkt);
    Ebene(const valarray&lt;T&gt; &amp; neuerFusspunkt, const valarray&lt;T&gt; &amp; neuerNormalenvektor);
    Ebene(const Ebene&lt;T&gt; &amp; ebene);

    bool istOberhalb (const valarray&lt;T&gt; &amp; punkt); // Punkt liegt in Richtung des Normalenvektors              oder in der Ebene
    bool istUnterhalb(const valarray&lt;T&gt; &amp; punkt); // Punkt liegt in Richtung des invertierten Normalenvektors oder in der Ebene
};

#endif

/***************/
/* Include.cpp */
/***************/

#include &quot;Include.h&quot;

template &lt;typename T&gt; Ebene&lt;T&gt;::Ebene() : fusspunkt(), normalenvektor()
{}

template &lt;typename T&gt; Ebene&lt;T&gt;::Ebene(const valarray&lt;T&gt; &amp; neuerFusspunkt) : fusspunkt(neuerFusspunkt), normalenvektor()
{}

template &lt;typename T&gt; Ebene&lt;T&gt;::Ebene(const valarray&lt;T&gt; &amp; neuerFusspunkt, const valarray&lt;T&gt; &amp; neuerNormalenvektor) : fusspunkt(neuerFusspunkt), normalenvektor(neuerNormalenvektor)
{}

template &lt;typename T&gt; Ebene&lt;T&gt;::Ebene(const Ebene&lt;T&gt; &amp; ebene) : fusspunkt(ebene.fusspunkt), normalenvektor(ebene.normalenvektor)
{}

template &lt;typename T&gt; bool Ebene&lt;T&gt;::istOberhalb(const valarray&lt;T&gt; &amp; punkt)
{
  return 0. &gt;= (this-&gt;normalenvektor * (this-&gt;fusspunkt - punkt)).sum();
}

template &lt;typename T&gt; bool Ebene&lt;T&gt;::istUnterhalb(const valarray&lt;T&gt; &amp; punkt)
{
  return 0. &lt;= (this-&gt;normalenvektor * (this-&gt;fusspunkt - punkt)).sum();
}
</code></pre>
<pre><code>C:\Users\Zsar\AppData\Local\Temp\ccjsHpv2.o:Test.c:(.text+0x156): undefined reference to `Ebene&lt;double&gt;::Ebene(std::valarray&lt;double&gt; const&amp;, std::valarray&lt;double&gt; const&amp;)'
C:\Users\Zsar\AppData\Local\Temp\ccjsHpv2.o:Test.c:(.text+0x160): undefined reference to `Ebene&lt;double&gt;::istOberhalb(std::valarray&lt;double&gt; const&amp;)'
C:\Users\Zsar\AppData\Local\Temp\ccjsHpv2.o:Test.c:(.text+0x1b0): undefined reference to `Ebene&lt;double&gt;::istUnterhalb(std::valarray&lt;double&gt; const&amp;)'
collect2.exe: error: ld returned 1 exit status
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/topic/314604/templates-und-pointer-to-member-function-in-verteilten-quelldateien</link><generator>RSS for Node</generator><lastBuildDate>Sat, 01 Aug 2026 05:58:47 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/314604.rss" rel="self" type="application/rss+xml"/><pubDate>Thu, 07 Mar 2013 18:37:49 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to templates und pointer-to-member-function in verteilten Quelldateien on Thu, 07 Mar 2013 18:44:39 GMT]]></title><description><![CDATA[<p><em>Die Beispiele sind natürlich bewusst einfach konstruiert und drum sinnfrei!</em></p>
<p>Nehmen wir an, wir hätten ein algebraisches Konstrukt definiert, sagen wir einmal eine Ebene. Da wäre es doch schön, wenn dieselbe für mehrere Datentypen funktionieren würde, fixed-point Ganzzahlen, double, vielleicht auch für Exotischeres.<br />
Da bietet es sich wohl an, das Ding als template zu definieren, mit dem numerischen Datentyp als Parameter.</p>
<p>Nun kommt man vielleicht in die Verlegenheit, dass man zwar weiß, wie oft eine Methode einer Klasse ausgeführt werden soll - aber nicht welche. Na, da lässt man sich eben einfach sagen, welche es denn sein soll, per Parameter.</p>
<p>Kombiniert man nun diese beiden Lösungen, will man also einen Zeiger auf die Methode einer template-Ebene herumreichen, so trifft man - zumindest bei minGW (G++ 4.7.0) - auf folgendes Kuriosum:</p>
<p>Ist die Ebene in der selben Quelldatei definiert, funktioniert's - ist sie das aber nicht, findet der Linker die angegebenen Methoden nicht.<br />
Definierte man die Ebene nun nicht als template - funktioniert es wiederum.</p>
<p>Was wäre zu tun, um dieses Unbill zu beseitigen, mit anderen Worten: seine allgemeine Ebene andernortes zu definieren ohne deshalb nicht mehr ihre Methoden zeigerhaft herumreichen zu können?</p>
<pre><code>#include &lt;iostream&gt;
#include &lt;valarray&gt;

using namespace std;

template &lt;typename T&gt; class Ebene
{
  protected:
    valarray&lt;T&gt; fusspunkt;
    valarray&lt;T&gt; normalenvektor;

  public:
    Ebene() : fusspunkt(), normalenvektor() {}
    Ebene(const valarray&lt;T&gt; &amp; neuerFusspunkt) : fusspunkt(neuerFusspunkt), normalenvektor() {}
    Ebene(const valarray&lt;T&gt; &amp; neuerFusspunkt, const valarray&lt;T&gt; &amp; neuerNormalenvektor) : fusspunkt(neuerFusspunkt), normalenvektor(neuerNormalenvektor) {}
    Ebene(const Ebene&lt;T&gt; &amp; ebene) : fusspunkt(ebene.fusspunkt), normalenvektor(ebene.normalenvektor) {}

    bool istOberhalb (const valarray&lt;T&gt; &amp; punkt) // Punkt liegt in Richtung des Normalenvektors              oder in der Ebene
    {
      return 0. &gt;= (this-&gt;normalenvektor * (this-&gt;fusspunkt - punkt)).sum();
    }
    bool istUnterhalb(const valarray&lt;T&gt; &amp; punkt) // Punkt liegt in Richtung des invertierten Normalenvektors oder in der Ebene
    {
      return 0. &lt;= (this-&gt;normalenvektor * (this-&gt;fusspunkt - punkt)).sum();
    }
};

bool punktLiegtGut(Ebene&lt;double&gt; &amp; ebene, const valarray&lt;double&gt; &amp; punkt, bool (Ebene&lt;double&gt;::* oberOderUnterhalb)(const valarray&lt;double&gt; &amp; punkt))
{
  return (ebene.*oberOderUnterhalb)(punkt);
}

int main ()
{
  valarray&lt;double&gt; normale(3);
  valarray&lt;double&gt; fuss(3);
  valarray&lt;double&gt; punkt(3);
  for(unsigned int z = 0; z &lt; 3; z++)
  {
    normale[z] = (double) z;
    fuss[z]    = (double)-z;
    punkt[z]   = (double)(z * (z % 2) - z * ((z + 1) % 2));
  }

  Ebene&lt;double&gt; e(fuss, normale);
  cout &lt;&lt; punktLiegtGut(e, punkt, &amp;Ebene&lt;double&gt;::istOberhalb) &lt;&lt; endl;
  cout &lt;&lt; punktLiegtGut(e, punkt, &amp;Ebene&lt;double&gt;::istUnterhalb) &lt;&lt; endl;

  return 0;
}
</code></pre>
<pre><code>/************/
/* main.cpp */
/************/

#include &lt;iostream&gt;
#include &lt;valarray&gt;

#include &quot;Include.h&quot;

using namespace std;

bool punktLiegtGut(Ebene&lt;double&gt; &amp; ebene, const valarray&lt;double&gt; &amp; punkt, bool (Ebene&lt;double&gt;::* oberOderUnterhalb)(const valarray&lt;double&gt; &amp; punkt))
{
  return (ebene.*oberOderUnterhalb)(punkt);
}

int main ()
{
  valarray&lt;double&gt; normale(3);
  valarray&lt;double&gt; fuss(3);
  valarray&lt;double&gt; punkt(3);
  for(unsigned int z = 0; z &lt; 3; z++)
  {
    normale[z] = (double) z;
    fuss[z]    = (double)-z;
    punkt[z]   = (double)(z * (z % 2) - z * ((z + 1) % 2));
  }

  Ebene&lt;double&gt; e(fuss, normale);
  cout &lt;&lt; punktLiegtGut(e, punkt, &amp;Ebene&lt;double&gt;::istOberhalb) &lt;&lt; endl;
  cout &lt;&lt; punktLiegtGut(e, punkt, &amp;Ebene&lt;double&gt;::istUnterhalb) &lt;&lt; endl;

  return 0;
}

/*************/
/* Include.h */
/*************/

#ifndef INCLUDE_H
#define INCLUDE_H

#include &lt;valarray&gt;

using namespace std;

template &lt;typename T&gt; class Ebene
{
  protected:
    valarray&lt;T&gt; fusspunkt;
    valarray&lt;T&gt; normalenvektor;

  public:
    Ebene();
    Ebene(const valarray&lt;T&gt; &amp; neuerFusspunkt);
    Ebene(const valarray&lt;T&gt; &amp; neuerFusspunkt, const valarray&lt;T&gt; &amp; neuerNormalenvektor);
    Ebene(const Ebene&lt;T&gt; &amp; ebene);

    bool istOberhalb (const valarray&lt;T&gt; &amp; punkt); // Punkt liegt in Richtung des Normalenvektors              oder in der Ebene
    bool istUnterhalb(const valarray&lt;T&gt; &amp; punkt); // Punkt liegt in Richtung des invertierten Normalenvektors oder in der Ebene
};

#endif

/***************/
/* Include.cpp */
/***************/

#include &quot;Include.h&quot;

template &lt;typename T&gt; Ebene&lt;T&gt;::Ebene() : fusspunkt(), normalenvektor()
{}

template &lt;typename T&gt; Ebene&lt;T&gt;::Ebene(const valarray&lt;T&gt; &amp; neuerFusspunkt) : fusspunkt(neuerFusspunkt), normalenvektor()
{}

template &lt;typename T&gt; Ebene&lt;T&gt;::Ebene(const valarray&lt;T&gt; &amp; neuerFusspunkt, const valarray&lt;T&gt; &amp; neuerNormalenvektor) : fusspunkt(neuerFusspunkt), normalenvektor(neuerNormalenvektor)
{}

template &lt;typename T&gt; Ebene&lt;T&gt;::Ebene(const Ebene&lt;T&gt; &amp; ebene) : fusspunkt(ebene.fusspunkt), normalenvektor(ebene.normalenvektor)
{}

template &lt;typename T&gt; bool Ebene&lt;T&gt;::istOberhalb(const valarray&lt;T&gt; &amp; punkt)
{
  return 0. &gt;= (this-&gt;normalenvektor * (this-&gt;fusspunkt - punkt)).sum();
}

template &lt;typename T&gt; bool Ebene&lt;T&gt;::istUnterhalb(const valarray&lt;T&gt; &amp; punkt)
{
  return 0. &lt;= (this-&gt;normalenvektor * (this-&gt;fusspunkt - punkt)).sum();
}
</code></pre>
<pre><code>C:\Users\Zsar\AppData\Local\Temp\ccjsHpv2.o:Test.c:(.text+0x156): undefined reference to `Ebene&lt;double&gt;::Ebene(std::valarray&lt;double&gt; const&amp;, std::valarray&lt;double&gt; const&amp;)'
C:\Users\Zsar\AppData\Local\Temp\ccjsHpv2.o:Test.c:(.text+0x160): undefined reference to `Ebene&lt;double&gt;::istOberhalb(std::valarray&lt;double&gt; const&amp;)'
C:\Users\Zsar\AppData\Local\Temp\ccjsHpv2.o:Test.c:(.text+0x1b0): undefined reference to `Ebene&lt;double&gt;::istUnterhalb(std::valarray&lt;double&gt; const&amp;)'
collect2.exe: error: ld returned 1 exit status
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2305123</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2305123</guid><dc:creator><![CDATA[Zsar]]></dc:creator><pubDate>Thu, 07 Mar 2013 18:44:39 GMT</pubDate></item><item><title><![CDATA[Reply to templates und pointer-to-member-function in verteilten Quelldateien on Thu, 07 Mar 2013 18:52:08 GMT]]></title><description><![CDATA[<p>Templates muessen in die .hpp.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2305125</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2305125</guid><dc:creator><![CDATA[Kellerautomat]]></dc:creator><pubDate>Thu, 07 Mar 2013 18:52:08 GMT</pubDate></item><item><title><![CDATA[Reply to templates und pointer-to-member-function in verteilten Quelldateien on Thu, 07 Mar 2013 19:04:58 GMT]]></title><description><![CDATA[<p>Hmm, das war ja... einfach. Darauf hätte ich in einem weniger dämlichen Zustande durchaus auch selbst kommen dürfen.</p>
<p>Ach weh, das erklärt dann wohl alles. Vielen Dank für den Denkersatz, ich wollte ihn am liebsten sogleich - fest installieren.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2305129</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2305129</guid><dc:creator><![CDATA[Zsar]]></dc:creator><pubDate>Thu, 07 Mar 2013 19:04:58 GMT</pubDate></item></channel></rss>