<?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-Klassen: class CDerived : public CBase&amp;lt;CDerived::Enum&amp;gt; HowTo?]]></title><description><![CDATA[<p>Hallo,</p>
<p>ich möchte eine Enum-Klasse implementieren, die neben den Enumerationswerten entsprechende String-Werte verwaltet.</p>
<p>Alter/klassischer Ansatz:</p>
<pre><code>enum Numbers
{
  One   = 1,
  Two   = 2,
  Three = 3
};
#define ENUM_NUMBER_ONE   TEXT(&quot;One&quot;)
#define ENUM_NUMBER_TWO   TEXT(&quot;Two&quot;)
#define ENUM_NUMBER_THREE TEXT(&quot;Three&quot;)
</code></pre>
<p>Neuer Ansatz:</p>
<p>- Eine Enum-Klasse soll die Enumeration und die korrespondierenden String-Werte in sich vereinen.<br />
- Typsicherheit soll gewährleistet sein.<br />
- Alle Enumerationsklassen sollen von einer Basisklasse abgeleitet sein, um über Basisklassen-Pointer zugreifen zu können.</p>
<p>Die String-Werte sollen in der Basis-Template-Klasse CBase verwaltet werden, die Enumeration selbst ist aber in einer abgeleiteten Klasse CDerived deklariert.</p>
<pre><code>template &lt;class T&gt; class CBase
{
  ...
};

class CDerived : public CBase&lt;CDerived::Enum&gt;  // C2065
{
public:
  enum Enum
  {
    One   = 1,
    Two   = 2,
    Three = 3
  };
}
</code></pre>
<p>Der aktuelle Code liefert &quot;C2065: 'Enum': undeclared identifier&quot;</p>
<p>Durch folgende Forward-Deklaration lässt sich der Code compilieren, wobei sich beide Klassendeklarationen gleich verhalten/zu verhalten scheinen:</p>
<pre><code>enum Enum;
class CDerived : public CBase&lt;CDerived::Enum&gt;
class CDerived2 : public CBase&lt;Enum&gt;
</code></pre>
<p>Ich verstehe zwar nicht, wieso dies nicht nur compiliert, sondern auch funktioniert, aber was soll's <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>Der Nachteil ist jedoch, dass hierdurch ständig von CDerived::Enum in Enum gecastet werden muss. Die Typsicherheit ist also futsch, da es sich bei Enum um eine leere Enumeration zu handeln scheint.</p>
<p>Folgende Forward-Deklaration funktioniert NICHT:</p>
<pre><code>class CDerived;
enum CDerived::Enum; // C2027
</code></pre>
<p>&quot;C2027: use of undefined type 'CDerived'&quot;<br />
Ok, verstehe ich. Aber mir fällt keine Alternative ein.</p>
<p>Frage:</p>
<p>1.) Hat jemand eine Idee, wie sich folgende Deklaration lauffähig machen lässt bzw. ein eindeutiges &quot;geht nicht (,weil...)&quot;?</p>
<pre><code>class CDerived : public CBase&lt;CDerived::Enum&gt;
</code></pre>
<p>2.) Hat jemand eine alternative Lösung zum CBase/CDerived-Ansatz parat?</p>
<p>Danke &amp; Gruß</p>
<p>Laerdris</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/248137/template-klassen-class-cderived-public-cbase-lt-cderived-enum-gt-howto</link><generator>RSS for Node</generator><lastBuildDate>Thu, 17 Sep 2026 04:33:03 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/248137.rss" rel="self" type="application/rss+xml"/><pubDate>Thu, 20 Aug 2009 08:23:08 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Template-Klassen: class CDerived : public CBase&amp;lt;CDerived::Enum&amp;gt; HowTo? on Thu, 20 Aug 2009 08:23:08 GMT]]></title><description><![CDATA[<p>Hallo,</p>
<p>ich möchte eine Enum-Klasse implementieren, die neben den Enumerationswerten entsprechende String-Werte verwaltet.</p>
<p>Alter/klassischer Ansatz:</p>
<pre><code>enum Numbers
{
  One   = 1,
  Two   = 2,
  Three = 3
};
#define ENUM_NUMBER_ONE   TEXT(&quot;One&quot;)
#define ENUM_NUMBER_TWO   TEXT(&quot;Two&quot;)
#define ENUM_NUMBER_THREE TEXT(&quot;Three&quot;)
</code></pre>
<p>Neuer Ansatz:</p>
<p>- Eine Enum-Klasse soll die Enumeration und die korrespondierenden String-Werte in sich vereinen.<br />
- Typsicherheit soll gewährleistet sein.<br />
- Alle Enumerationsklassen sollen von einer Basisklasse abgeleitet sein, um über Basisklassen-Pointer zugreifen zu können.</p>
<p>Die String-Werte sollen in der Basis-Template-Klasse CBase verwaltet werden, die Enumeration selbst ist aber in einer abgeleiteten Klasse CDerived deklariert.</p>
<pre><code>template &lt;class T&gt; class CBase
{
  ...
};

class CDerived : public CBase&lt;CDerived::Enum&gt;  // C2065
{
public:
  enum Enum
  {
    One   = 1,
    Two   = 2,
    Three = 3
  };
}
</code></pre>
<p>Der aktuelle Code liefert &quot;C2065: 'Enum': undeclared identifier&quot;</p>
<p>Durch folgende Forward-Deklaration lässt sich der Code compilieren, wobei sich beide Klassendeklarationen gleich verhalten/zu verhalten scheinen:</p>
<pre><code>enum Enum;
class CDerived : public CBase&lt;CDerived::Enum&gt;
class CDerived2 : public CBase&lt;Enum&gt;
</code></pre>
<p>Ich verstehe zwar nicht, wieso dies nicht nur compiliert, sondern auch funktioniert, aber was soll's <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>Der Nachteil ist jedoch, dass hierdurch ständig von CDerived::Enum in Enum gecastet werden muss. Die Typsicherheit ist also futsch, da es sich bei Enum um eine leere Enumeration zu handeln scheint.</p>
<p>Folgende Forward-Deklaration funktioniert NICHT:</p>
<pre><code>class CDerived;
enum CDerived::Enum; // C2027
</code></pre>
<p>&quot;C2027: use of undefined type 'CDerived'&quot;<br />
Ok, verstehe ich. Aber mir fällt keine Alternative ein.</p>
<p>Frage:</p>
<p>1.) Hat jemand eine Idee, wie sich folgende Deklaration lauffähig machen lässt bzw. ein eindeutiges &quot;geht nicht (,weil...)&quot;?</p>
<pre><code>class CDerived : public CBase&lt;CDerived::Enum&gt;
</code></pre>
<p>2.) Hat jemand eine alternative Lösung zum CBase/CDerived-Ansatz parat?</p>
<p>Danke &amp; Gruß</p>
<p>Laerdris</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1763913</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1763913</guid><dc:creator><![CDATA[Laerdris]]></dc:creator><pubDate>Thu, 20 Aug 2009 08:23:08 GMT</pubDate></item><item><title><![CDATA[Reply to Template-Klassen: class CDerived : public CBase&amp;lt;CDerived::Enum&amp;gt; HowTo? on Thu, 20 Aug 2009 09:06:47 GMT]]></title><description><![CDATA[<pre><code class="language-cpp">#include &lt;iostream&gt;
using namespace std;

enum Farbe
{
	ROT,GRUEN,BLAU,GELB,
};
char const* name(Farbe f)
{
	static char const* namen[]={&quot;ROT&quot;,&quot;GRUEN&quot;,&quot;BLAU&quot;,&quot;GELB&quot;,};
	return namen[f];
}

enum Land
{
	ENGLAND,DEUTSCHLAND,USA,
};
char const* name(Land l)
{
	static char const* namen[]={&quot;ENGLAND&quot;,&quot;DEUTSCHLAND&quot;,&quot;USA&quot;,};
	return namen[l];
}

int main()
{
	Farbe f=ROT;
	cout&lt;&lt;name(f)&lt;&lt;'\n';
	cout&lt;&lt;name(GRUEN)&lt;&lt;'\n';
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1763927</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1763927</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Thu, 20 Aug 2009 09:06:47 GMT</pubDate></item><item><title><![CDATA[Reply to Template-Klassen: class CDerived : public CBase&amp;lt;CDerived::Enum&amp;gt; HowTo? on Thu, 20 Aug 2009 09:20:24 GMT]]></title><description><![CDATA[<p>Vielleicht reicht ja auch der op &lt;&lt;:</p>
<pre><code>enum Monat {Jan, Feb, Mar, Apr, Mai, Jun, Jul, Aug, Sep, Okt, Nov, Dez};

std::ostream &amp; operator &lt;&lt; (std::ostream &amp; out, Monat monat)
{
    static char const * namen[] = {
       &quot;Januar&quot;, &quot;Februar&quot;, &quot;März&quot;, &quot;April&quot;,
       &quot;Mai&quot;, &quot;Juni&quot;, &quot;Juli&quot;, &quot;August&quot;,
       &quot;September&quot;, &quot;Oktober&quot;, &quot;November&quot;, &quot;Dezember&quot;};

    out &lt;&lt; namen[monat];
    return out;
}

int main()
{
  Monat m = Jul;
  std::cout &lt;&lt; m &lt;&lt; std::endl;
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1763969</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1763969</guid><dc:creator><![CDATA[jencas]]></dc:creator><pubDate>Thu, 20 Aug 2009 09:20:24 GMT</pubDate></item><item><title><![CDATA[Reply to Template-Klassen: class CDerived : public CBase&amp;lt;CDerived::Enum&amp;gt; HowTo? on Thu, 20 Aug 2009 09:27:07 GMT]]></title><description><![CDATA[<p>Hallo,</p>
<p>heissen Dank für die schnellen Antworten!</p>
<p>Prinzipiell sind beide vorgeschlagenen Lösungen ausreichend bis perfekt für eine einzelne Enumeration.</p>
<p>Ich würde aber gerne noch einen Schritt weiter gehen:</p>
<p>Nehmen wir an, es gäbe neben &quot;Farbe&quot; auch noch &quot;Form&quot;. Beide Klassen/Typen/Enumerationen sind in meiner eigentlichen Anwendung voneinander nicht abhängig, also würden 2 separate Klassen genügen.</p>
<p>Farbe und Form werden aus Text-Configdateien ausgelesen und von String in Enum konvertiert. Auch hierfür ist keine Abhängigkeit (in Form einer Basisklasse) nötig.</p>
<p>Nun möchte ich aber eine grafische Oberfläche implementieren und dynamisch per Code initialisieren/konfigurieren, und dafür wäre es hilfreich, wenn &quot;Form&quot; und &quot;Farbe&quot; eine gemeinsame Basis hätten und das ganze auch noch Typsicher (per Template-Base) wäre:</p>
<pre><code>class CEnumFarbe : public CEnumBase&lt;CEnumFarbe::Enum&gt;
{
  enum Enum
  {
    Red   = 1,
    Green = 2,
    Blue  = 3
  };
  static char const* names[]={&quot;Red&quot;,&quot;Green&quot;,&quot;Blue&quot;}; 
};
class CEnumForm  : public CEnumBase&lt;CEnumForm ::Enum&gt;
{
  enum Enum
  {
    Circle = 1,
    Square = 2,
    Triangle = 3
  };
  static char const* names[]={&quot;Circle&quot;,&quot;Square&quot;,&quot;Triangle&quot;}; 
};

BOOL SetChoices(UINT uCtrlID, CEnumBase* pEnumBase) { ... } ;

CEnumFarbe eFarbe;
CEnumForm  eForm;
SetChoices(IDC_COMBO_FARBE, eFarbe);
SetChoices(IDC_COMBO_FORM,  eForm);
</code></pre>
<p>Wär doch entzückend, wenn alle meine 'intelligenten' Enum-Klassen ihre jeweiligen Wertebereiche enumerieren könnten und somit meine Controls dynamisch füllen würden.</p>
<p>Hmm, vielleicht ein bisschen übertrieben parametrisiert, aber irgendwie doch elegant, oder?</p>
<p>Zumindest wenn's so gehen würde, aber es scheitert ja leider an der Übergabe von &quot;CDerived::Enum&quot; als Template-Parameter für &quot;CBase&lt;class T&gt;&quot; während der Deklaration von &quot;CDerived&quot; (also bevor der Compiler von der Existenz von &quot;CDerived::Enum&quot; weiss)</p>
<p>Danke und Gruß</p>
<p>Laerdris</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1763970</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1763970</guid><dc:creator><![CDATA[Laerdris]]></dc:creator><pubDate>Thu, 20 Aug 2009 09:27:07 GMT</pubDate></item><item><title><![CDATA[Reply to Template-Klassen: class CDerived : public CBase&amp;lt;CDerived::Enum&amp;gt; HowTo? on Thu, 20 Aug 2009 09:33:41 GMT]]></title><description><![CDATA[<pre><code class="language-cpp">#include &lt;iostream&gt;
using namespace std;

template&lt;typename ENUM&gt;
struct EnumDescriber;

enum Farbe
{
	ROT,GRUEN,BLAU,GELB,
};
template&lt;&gt;
struct EnumDescriber&lt;Farbe&gt;
{
	static char const* namen[4];
};
char const* EnumDescriber&lt;Farbe&gt;::namen[4]={&quot;ROT&quot;,&quot;GRUEN&quot;,&quot;BLAU&quot;,&quot;GELB&quot;,};

enum Land
{
	ENGLAND,DEUTSCHLAND,USA,
};
template&lt;&gt;
struct EnumDescriber&lt;Land&gt;
{
	static char const* namen[3];
};
char const* EnumDescriber&lt;Land&gt;::namen[3]={&quot;ENGLAND&quot;,&quot;DEUTSCHLAND&quot;,&quot;USA&quot;,};

template&lt;size_t anzahl&gt;
void fillComboBox(char const* (&amp;namen)[anzahl])
{
	for(int i=0;i!=anzahl;++i)
		cout&lt;&lt;i&lt;&lt;' '&lt;&lt;namen[i]&lt;&lt;'\n';
}

int main()
{
	Farbe f=ROT;
	cout&lt;&lt;EnumDescriber&lt;Farbe&gt;::namen[f]&lt;&lt;'\n';
	fillComboBox(EnumDescriber&lt;Land&gt;::namen);
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1763980</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1763980</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Thu, 20 Aug 2009 09:33:41 GMT</pubDate></item><item><title><![CDATA[Reply to Template-Klassen: class CDerived : public CBase&amp;lt;CDerived::Enum&amp;gt; HowTo? on Thu, 20 Aug 2009 09:38:51 GMT]]></title><description><![CDATA[<p>Hallo Volkard,</p>
<p>das sieht ja auf den ersten Blick mal sehr interessant aus. Werd ich gleich mal testen und zu verstehen versuchen <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>Gruß</p>
<p>Laerdris</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1763984</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1763984</guid><dc:creator><![CDATA[Laerdris]]></dc:creator><pubDate>Thu, 20 Aug 2009 09:38:51 GMT</pubDate></item><item><title><![CDATA[Reply to Template-Klassen: class CDerived : public CBase&amp;lt;CDerived::Enum&amp;gt; HowTo? on Mon, 24 Aug 2009 07:58:25 GMT]]></title><description><![CDATA[<p>Hallo,</p>
<p>ich hab den Vorschlag mal zu folgendem Ergebnis eingedampft:</p>
<pre><code>// .h
template&lt;typename T&gt; class JPEnum
{ 
public:
    static char const* namen[]; 
    static T           werte[];

    JPEnum(const T&amp; TValue);
    JPEnum(char* lpszValue);
    ~JPEnum();

    BOOL  IsValid();
    operator const char*();
    T&amp; operator=(char* lpszValue);

private:
    T m_TValue;
}; 

enum Farbe 
{ 
    ROT   = 2,
    GRUEN = 3,
    BLAU  = 5,
    GELB  = 7 
}; 
char const* JPEnum&lt;Farbe&gt;::namen[]={&quot;ROT&quot;,&quot;GRUEN&quot;,&quot;BLAU&quot;,&quot;GELB&quot;,NULL}; 
Farbe       JPEnum&lt;Farbe&gt;::werte[]={ROT, GRUEN, BLAU, GELB};

enum Land 
{ 
    ENGLAND      = 10,
    DEUTSCHLAND  = 20,
    USA          = 30
};
char const* JPEnum&lt;Land&gt; ::namen[]={&quot;ENGLAND&quot;,&quot;DEUTSCHLAND&quot;,&quot;USA&quot;,NULL}; 
Land        JPEnum&lt;Land&gt; ::werte[]={ENGLAND,DEUTSCHLAND,USA};

// .cpp

template&lt;typename T&gt; JPEnum&lt;T&gt;::JPEnum(const T&amp; TValue) : m_TValue(TValue) {}

template&lt;typename T&gt; JPEnum&lt;T&gt;::JPEnum(char* lpszValue) : m_TValue((T)-1)
{
  for(int intIndex = 0 ; namen[intIndex] != NULL ; intIndex++)
  {
    if(!_stricmp(lpszValue, namen[intIndex]))
    {
      this-&gt;m_TValue = werte[intIndex];
      return;
    }
  }
}

template&lt;typename T&gt; JPEnum&lt;T&gt;::~JPEnum() { }

template&lt;typename T&gt; JPEnum&lt;T&gt;::operator const char*()
{
  for(int intIndex = 0 ; namen[intIndex] != NULL ; intIndex++)
  {
    if(m_TValue == werte[intIndex])
    {
      return namen[intIndex];
    }
  }
  return NULL;
};

//  ======================================================================

template&lt;typename T&gt; T&amp; JPEnum&lt;T&gt;::operator=(char* lpszValue)
{
  for(int intIndex = 0 ; namen[intIndex] != NULL ; intIndex++)
  {
    if(!_stricmp(lpszValue, namen[intIndex]))
    {
      this-&gt;m_TValue = werte[intIndex];
      return this-&gt;m_TValue;
    }
  }
  this-&gt;m_TValue = (T)-1;
  return this-&gt;m_TValue;
};

template&lt;typename T&gt; BOOL JPEnum&lt;T&gt;::IsValid()
{
  return (this-&gt;m_TValue != (T)-1);
}

void Test()
{ 
  // Land
  JPEnum&lt;Land&gt; l = DEUTSCHLAND;
  const char* lpszLand = (const char*) l;

  // Farbe
  JPEnum&lt;Farbe&gt; f1 = &quot;BLAU&quot;;
  JPEnum&lt;Farbe&gt; f2(&quot;Nix&quot;);
  f2 = &quot;Gruen&quot;;
  f2 = f1;
  const char* lpszFarbe = (const char*) f2;
}
</code></pre>
<p>Das ist zwar nicht exakt das gewünschte Ergebnis, reicht aber aus und hilft mir weiter.</p>
<p>Optimiert ist ebenfalls noch nicht, die public member müssen noch privatisiert und mit get/set methoden versehen werden.</p>
<p>Gestolpert bin ich übrigens bei folgender Zeile:</p>
<pre><code>JPEnum&lt;Farbe&gt; f1 = &quot;BLAU&quot;;
</code></pre>
<p>Hier hatte ich einen Aufruf von operator= erwartet, bis ich endlich darauf kam dass hier der constructor aufgerufen wird <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f61b.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_with_tongue"
      title=":P"
      alt="😛"
    /></p>
<p>Vielen Dank für eure Vorschläge, die Idee mit der Überladung von operator&lt;&lt; fand ich ebenfalls interessant.</p>
<p>Gruß</p>
<p>Laerdris</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1765630</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1765630</guid><dc:creator><![CDATA[Laerdris]]></dc:creator><pubDate>Mon, 24 Aug 2009 07:58:25 GMT</pubDate></item></channel></rss>