<?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[Check für is member function pointer]]></title><description><![CDATA[<p>Hi zusammen,</p>
<p>ich suche einen Methode mit der ich überprüfen kann ob ein Type T ein Member function ptr is oder nicht.</p>
<p>also sowas in der form<br />
is_member_function_ptr&lt;void (MyClass::<em>)(void)&gt;::value =&gt; true<br />
is_member_function_ptr&lt;void (</em>)(int)&gt;::value =&gt; false da function</p>
<p>Das ganze muss mit C++03 funktionieren, VS + gcc<br />
Boost kann ich leider nicht verwenden.</p>
<p>Hat jemand ne idee?<br />
Das ich SFINAE verwenden muss ist klar, aber ich möchte ungern eine substitution für alle mögliche argument variationen niederschreiben.<br />
Was denkt ihr?</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/306845/check-für-is-member-function-pointer</link><generator>RSS for Node</generator><lastBuildDate>Fri, 07 Aug 2026 03:42:06 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/306845.rss" rel="self" type="application/rss+xml"/><pubDate>Wed, 08 Aug 2012 18:59:23 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Check für is member function pointer on Wed, 08 Aug 2012 18:59:23 GMT]]></title><description><![CDATA[<p>Hi zusammen,</p>
<p>ich suche einen Methode mit der ich überprüfen kann ob ein Type T ein Member function ptr is oder nicht.</p>
<p>also sowas in der form<br />
is_member_function_ptr&lt;void (MyClass::<em>)(void)&gt;::value =&gt; true<br />
is_member_function_ptr&lt;void (</em>)(int)&gt;::value =&gt; false da function</p>
<p>Das ganze muss mit C++03 funktionieren, VS + gcc<br />
Boost kann ich leider nicht verwenden.</p>
<p>Hat jemand ne idee?<br />
Das ich SFINAE verwenden muss ist klar, aber ich möchte ungern eine substitution für alle mögliche argument variationen niederschreiben.<br />
Was denkt ihr?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2240213</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2240213</guid><dc:creator><![CDATA[Nash26]]></dc:creator><pubDate>Wed, 08 Aug 2012 18:59:23 GMT</pubDate></item><item><title><![CDATA[Reply to Check für is member function pointer on Wed, 08 Aug 2012 19:57:40 GMT]]></title><description><![CDATA[<pre><code class="language-cpp">template &lt;class T&gt;          bool is_mfun (T*    ) { return false; }
template &lt;class C, class T&gt; bool is_mfun (T C::*) { return true;  }
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2240232</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2240232</guid><dc:creator><![CDATA[arogmyxdfa]]></dc:creator><pubDate>Wed, 08 Aug 2012 19:57:40 GMT</pubDate></item><item><title><![CDATA[Reply to Check für is member function pointer on Wed, 08 Aug 2012 21:16:03 GMT]]></title><description><![CDATA[<p>arogmyxdfa schrieb:</p>
<blockquote>
<pre><code class="language-cpp">template &lt;class T&gt;          bool is_mfun (T*    ) { return false; }
template &lt;class C, class T&gt; bool is_mfun (T C::*) { return true;  }
</code></pre>
</blockquote>
<p>Das prüft lediglich, ob du einen Pointer auf einen Member hast, nicht einen Pointer auf eine Memberfunktion. Zudem wird es einen Fehler bei allen Nicht-Pointer-Aufrufen geben...</p>
<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/22803">@Nash26</a>:<br />
Tja, ohne Variadic Templates wird dir wohl nichts anderes übrig bleiben, als is_member_function_ptr für eine ausreichende Anzahl an Parametern zu spezialisieren:</p>
<pre><code class="language-cpp">template&lt;typename T&gt; struct is_member_function_ptr
{
    static const bool value = false;
};

template&lt;typename Ret, typename Class&gt; struct is_member_function_ptr&lt;Ret (Class::*)()&gt;
{
    static const bool value = true;
};

template&lt;typename Ret, typename Class, typename T1&gt; struct is_member_function_ptr&lt;Ret (Class::*)(T1)&gt;
{
    static const bool value = true;
};

template&lt;typename Ret, typename Class, typename T1, typename T2&gt; struct is_member_function_ptr&lt;Ret (Class::*)(T1, T2)&gt;
{
    static const bool value = true;
};

//...
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2240263</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2240263</guid><dc:creator><![CDATA[wxSkip]]></dc:creator><pubDate>Wed, 08 Aug 2012 21:16:03 GMT</pubDate></item><item><title><![CDATA[Reply to Check für is member function pointer on Wed, 08 Aug 2012 22:29:16 GMT]]></title><description><![CDATA[<p>wxSkip schrieb:</p>
<blockquote>
<p>arogmyxdfa schrieb:</p>
<blockquote>
<pre><code class="language-cpp">template &lt;class T&gt;          bool is_mfun (T*    ) { return false; }
template &lt;class C, class T&gt; bool is_mfun (T C::*) { return true;  }
</code></pre>
</blockquote>
<p>Das prüft lediglich, ob du einen Pointer auf einen Member hast, nicht einen Pointer auf eine Memberfunktion.</p>
</blockquote>
<p>Nicht ganz, auch Zeiger-auf-non-const-Memberfunktionen sind erfasst (in diesem Fall wird T als Funktionstyp deduziert).</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2240268</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2240268</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Wed, 08 Aug 2012 22:29:16 GMT</pubDate></item><item><title><![CDATA[Reply to Check für is member function pointer on Thu, 09 Aug 2012 06:14:14 GMT]]></title><description><![CDATA[<p>Kennt ihr das Buch C++ Templates the complete guide?</p>
<p>Dort schreibt der Autor das es auch ohne die vielen parameter variationen geht:<br />
Hier benutzt er es um zu überprüfen ob eine Funktion gegeben ist oder nicht.<br />
<a href="http://www.josuttis.com/tmplbook/functors/typet.hpp.html" rel="nofollow">http://www.josuttis.com/tmplbook/functors/typet.hpp.html</a></p>
<p>@arogmyxdfa<br />
bei anderen typen soll es aber nicht zum compile Fehler kommen</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2240289</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2240289</guid><dc:creator><![CDATA[Nash26]]></dc:creator><pubDate>Thu, 09 Aug 2012 06:14:14 GMT</pubDate></item><item><title><![CDATA[Reply to Check für is member function pointer on Thu, 09 Aug 2012 08:33:25 GMT]]></title><description><![CDATA[<p>Nash26 schrieb:</p>
<blockquote>
<p>Boost kann ich leider nicht verwenden.</p>
</blockquote>
<p>Was hindert dich? Die typetraits von boost sind header-only, keine Installation, kein Linken, kein separates Übersetzen von Biblitoheken nötig.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2240309</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2240309</guid><dc:creator><![CDATA[pumuckl]]></dc:creator><pubDate>Thu, 09 Aug 2012 08:33:25 GMT</pubDate></item><item><title><![CDATA[Reply to Check für is member function pointer on Thu, 09 Aug 2012 08:45:52 GMT]]></title><description><![CDATA[<p>Nicht ganz das, was du suchst, aber vielleicht enthaelt es Anregungen: <a href="http://stackoverflow.com/questions/4353878/checking-whether-a-template-argument-has-a-member-function" rel="nofollow">http://stackoverflow.com/questions/4353878/checking-whether-a-template-argument-has-a-member-function</a></p>
<p>Die Frage ist natuerlich, warum du das brauchst!</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2240311</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2240311</guid><dc:creator><![CDATA[knivil]]></dc:creator><pubDate>Thu, 09 Aug 2012 08:45:52 GMT</pubDate></item><item><title><![CDATA[Reply to Check für is member function pointer on Thu, 09 Aug 2012 10:22:36 GMT]]></title><description><![CDATA[<p>Nash26 schrieb:</p>
<blockquote>
<p>Kennt ihr das Buch C++ Templates the complete guide?</p>
<p>Dort schreibt der Autor das es auch ohne die vielen parameter variationen geht:<br />
Hier benutzt er es um zu überprüfen ob eine Funktion gegeben ist oder nicht.<br />
<a href="http://www.josuttis.com/tmplbook/functors/typet.hpp.html" rel="nofollow">http://www.josuttis.com/tmplbook/functors/typet.hpp.html</a></p>
<p>@arogmyxdfa<br />
bei anderen typen soll es aber nicht zum compile Fehler kommen</p>
</blockquote>
<p>Dann hast du doch schon eine Lösung.<br />
In C++03 gibt es keine schöne Lösung dafür, da es keine Möglichkeit gibt, den Typ von Memberfunktionszeiger generisch aufzuschreiben (mangels variadic templates).<br />
Es bleiben zwei Alternativen:<br />
1. viele Spezialisierungen für ausreichend viele Parameter, Nachteil: eine Menge Codeduplikation, folglich langsames Compilieren, nicht allgemeingültig, falls doch mal längere Parameterlisten benötigt werden<br />
2. durch Eliminierung, wenn alle anderen Typen ausgeschlossen werden, muss ein Memberfunktionszeiger übrig bleiben, Nachteil: funktioniert ggf. nicht mehr, wenn weitere Typen dazukommen, die usprünglich nicht existierten (Compilererweiterungen, neue Standards...).</p>
<p>Das Testen auf non-const-non-volatile-Memberfunktionszeiger ist einfach. Schwierigkeiten machen nur const,volatile und const volatile-Memberfunktionen:</p>
<pre><code class="language-cpp">template &lt;bool b&gt; struct bool_ { static const bool value = b; };
typedef bool_&lt;false&gt; false_type;
typedef bool_&lt;true&gt; true_type;

template &lt;typename T, typename U&gt; struct is_same : false_type {};
template &lt;typename T&gt; struct is_same&lt;T, T&gt; : true_type {};

template &lt;typename T&gt; struct is_function : is_same&lt;void(T),void(T*)&gt; {};
// Spezialisierungen für Typen, für die void(T) oder void(T*) ill-formed ist:
// leidet unter dem gleichen Problem wie 2., weil auch für rvalue-Referenzen spezialisiert werden müsste; kann man durch den sizeof-SFINAE-Trick in den Griff kriegen, ist mir aber hier zuviel Schreibarbeit
template &lt;&gt; struct is_function&lt;const void&gt; : false_type {};            // 
template &lt;&gt; struct is_function&lt;volatile void&gt; : false_type {};         // kann nicht als Funktionsparameter auftreten (da immer unvollständig), die Sonderregel gilt nur für unqualifiziertes void
template &lt;&gt; struct is_function&lt;const volatile void&gt; : false_type {};   //
template &lt;typename T&gt; struct is_function&lt;T&amp;&gt; : false_type {}; // kann keine Zeiger auf Referenzen bilden

template &lt;typename T&gt; struct is_mem_fun_ptr : false_type {};
template &lt;typename T, typename C&gt; struct is_mem_fun_ptr&lt;T C::*&gt; : is_function&lt;T&gt; {};
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2240318</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2240318</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Thu, 09 Aug 2012 10:22:36 GMT</pubDate></item><item><title><![CDATA[Reply to Check für is member function pointer on Thu, 09 Aug 2012 18:17:07 GMT]]></title><description><![CDATA[<p>ist ja interesant, dein code funktioniert. Prima.</p>
<pre><code>template &lt;typename T, typename C&gt; struct is_mem_fun_ptr&lt;T C::*&gt; : is_function&lt;T&gt; {};
</code></pre>
<p>Aber warum wird diese spezialisierung instanziert, obwohl ich ein ein type mit 10 parametern übergebe?</p>
<p>Soweit ich das jetzt verstehe, brichst du das ganze schnell runter zu einem<br />
test für is_function_ptr.</p>
<p>Das hier verstehe ich leider nicht:</p>
<pre><code>template &lt;typename T&gt; struct is_function : is_same&lt;void(T),void(T*)&gt; {};
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2240501</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2240501</guid><dc:creator><![CDATA[Nash26]]></dc:creator><pubDate>Thu, 09 Aug 2012 18:17:07 GMT</pubDate></item><item><title><![CDATA[Reply to Check für is member function pointer on Thu, 09 Aug 2012 18:52:06 GMT]]></title><description><![CDATA[<p>Nash26 schrieb:</p>
<blockquote>
<p>ist ja interesant, dein code funktioniert. Prima.</p>
<pre><code>template &lt;typename T, typename C&gt; struct is_mem_fun_ptr&lt;T C::*&gt; : is_function&lt;T&gt; {};
</code></pre>
<p>Aber warum wird diese spezialisierung instanziert, obwohl ich ein ein type mit 10 parametern übergebe?</p>
</blockquote>
<p>Weil T selbst ein Funktionstyp sein kann. Und das passiert genau dann, wenn du das Template mit einem Zeiger auf non-const-non-volatile-Memberfunktion fütterst.<br />
Nimmst du in</p>
<pre><code class="language-cpp">T (C::*)(...)
</code></pre>
<p>den Deklarator ::* weg, bleibt ein Funktionstyp stehen. Leider können auf diese weise const und volatile Memberfunktionen nicht verarbeitet werden, weil Funktionstypen nicht qualifiziert sein dürfen (eine Einschränkung, für die mehr der Grund nie ganz klar geworden ist; dass Funktionen selbst nie qualifiziert sind, muss ja nichts mit dem Typen zu tun haben). Das führt zu der kuriosen Eigenschaft dass in z.B.</p>
<pre><code class="language-cpp">T (C::*)(...)const
</code></pre>
<p>nach Wegnahme des Deklarator ::* etwas steht, was kein (legaler) Typ ist. Da Deklaratoren aber eigentlich einen Typ aus einem anderen ableiten, ist das in meinem Augen seltsam.</p>
<p>Nash26 schrieb:</p>
<blockquote>
<p>Das hier verstehe ich leider nicht:</p>
<pre><code>template &lt;typename T&gt; struct is_function : is_same&lt;void(T),void(T*)&gt; {};
</code></pre>
</blockquote>
<p>Der Test basiert auf den Besonderheiten die für die Deklarationen von Funktionsparametern gelten. Wird ein Funktionsparameter als Funktionstyp deklariert, so transformiert der Compiler das in eine Deklaration eines Funktionszeigers als Parameter (analog für Arrays, allerdings ist das Ergebnis der Transformation dort nicht ein Zeiger auf das Array sondern einer auf den Elementtyp). Es spielt also bei Funktionenparametern keine Rolle, ob ausdrücklich ein Zeiger deklariert wird, die Deklaration verweist trotzdem auf den selben Typ. Und das gilt so nur für Funktionstypen.</p>
<p>Dein verlinkter Code nutzt übrigens die gleiche Eigenschaft, nur wird hier der sizeof-Überladungstrick angewendet.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2240511</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2240511</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Thu, 09 Aug 2012 18:52:06 GMT</pubDate></item><item><title><![CDATA[Reply to Check für is member function pointer on Thu, 09 Aug 2012 20:32:35 GMT]]></title><description><![CDATA[<p>ach du grüne neune und ich dachte ich wusste etwas über C++ und templates.</p>
<p>Das hier ist eine Deklarator?</p>
<pre><code class="language-cpp">::*
</code></pre>
<p>Was ist denn ein FunktionsType? Du meinst wohl eher wenn ich in</p>
<pre><code class="language-cpp">T (C::*)(...)
</code></pre>
<p>&quot;C::&quot; weglasse wird es ein function pointer?</p>
<pre><code class="language-cpp">T (*)(...)
</code></pre>
<p>Was meinst du mit</p>
<blockquote>
<p>qualifiziert</p>
</blockquote>
<p>in</p>
<blockquote>
<p>Funktionstypen nicht qualifiziert sein dürfen</p>
</blockquote>
<p>?</p>
<p>Es würde mir für das Verständnis extrem helfen wenn ich die einzelnen compiler schritte sehen könnte.</p>
<p>Beispiel:</p>
<pre><code class="language-cpp">struct Foo
{
void func(int,int) {}
};
template&lt;class T&gt;
void call(T member)
{
    bool result = is_mem_fun_ptr&lt;T&gt;::value;
}

call(&amp;Foo::func);
</code></pre>
<p>führt doch zu:</p>
<pre><code class="language-cpp">//Schritt 1:

template &lt;typename T, typename C&gt; struct is_mem_fun_ptr&lt;void Foo::*&gt; : is_function&lt;void&gt; {};
</code></pre>
<pre><code class="language-cpp">//Schritt 2:

template &lt;typename T&gt; struct is_function : is_same&lt;void(void),void(void*)&gt; {};
</code></pre>
<p>mhm aber das macht doch keinen sinn...</p>
<p>PS: Das code Beispiel aus dem Buch hat überhaupt nicht funktioniert, zumindest nicht mit VS2008</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2240528</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2240528</guid><dc:creator><![CDATA[Nash26]]></dc:creator><pubDate>Thu, 09 Aug 2012 20:32:35 GMT</pubDate></item><item><title><![CDATA[Reply to Check für is member function pointer on Thu, 09 Aug 2012 20:41:38 GMT]]></title><description><![CDATA[<p>&quot;Qualifiziert&quot; bedeutet, dass hinter einer Memberfunktion ein const und/oder ein volatile steht. Das bezieht sich auf den this-Pointer, der ja ohne das C nicht mehr vorhanden ist.</p>
<p>Bei Schritt 1 hast du dich geirrt:</p>
<pre><code class="language-cpp">//Schritt 1:

template &lt;typename T, typename C&gt; struct is_mem_fun_ptr&lt;void(int, int) Foo::*&gt; : is_function&lt;void(int, int)&gt; {};
</code></pre>
<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/19375">@SeppJ</a>: Wenn ich dich richtig verstanden habe, dann ist ein Funktionstyp mit oder ohne Zeiger das gleiche. Warum verwendest du dann nicht is_same&lt;T, T*&gt;?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2240529</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2240529</guid><dc:creator><![CDATA[wxSkip]]></dc:creator><pubDate>Thu, 09 Aug 2012 20:41:38 GMT</pubDate></item><item><title><![CDATA[Reply to Check für is member function pointer on Thu, 09 Aug 2012 21:31:35 GMT]]></title><description><![CDATA[<p>Nash26 schrieb:</p>
<blockquote>
<p>ach du grüne neune und ich dachte ich wusste etwas über C++ und templates.</p>
<p>Das hier ist eine Deklarator?</p>
<pre><code class="language-cpp">::*
</code></pre>
<p>Was ist denn ein FunktionsType? Du meinst wohl eher wenn ich in</p>
<pre><code class="language-cpp">T (C::*)(...)
</code></pre>
<p>&quot;C::&quot; weglasse wird es ein function pointer?</p>
<pre><code class="language-cpp">T (*)(...)
</code></pre>
</blockquote>
<p>Ein Zeiger auf Member wird deklariert durch<br />
<em>nested-name-specifier</em> * <em>attribute-specifier-seq</em><sub>opt</sub> <em>cv-qualifier-seq</em><sub>opt</sub> D1<br />
also einem Bezeichner gefolgt vonm scope-Operator, gefolgt von einem Stern, gefolgt von etc., ich hätte also korrekterweise schreiben müssen:</p>
<pre><code class="language-cpp">C::*
</code></pre>
<p>wegzulassen.</p>
<p>Nash26 schrieb:</p>
<blockquote>
<p>Was meinst du mit</p>
<blockquote>
<p>qualifiziert</p>
</blockquote>
<p>in</p>
<blockquote>
<p>Funktionstypen nicht qualifiziert sein dürfen</p>
</blockquote>
<p>?</p>
</blockquote>
<p>Qualifikation bedeutet immer, dass zu einer Entität noch etwas dazu kommt, wenn nichts weiter dazu gesagt wird, bezieht sich das in der Regel darauf, das ein Typ oder ein Objekt zusätzlich als const und/oder volatile bestimmt (qualifiziert) wird. Im Zusammenhang mit Namelookup bezieht es sich auf Bezeichner, bei denen zusätzlich ein Scope angegeben wird. Die konkrete Bedeutung muss man jeweils dem Kontext entnehmen, aus Bequemlichkeit schreibe ich es nicht immer ausdrücklich hin.</p>
<p>Nash26 schrieb:</p>
<blockquote>
<p>Es würde mir für das Verständnis extrem helfen wenn ich die einzelnen compiler schritte sehen könnte.</p>
<p>Beispiel:</p>
<pre><code class="language-cpp">struct Foo
{
void func(int,int) {}
};
template&lt;class T&gt;
void call(T member)
{
    bool result = is_mem_fun_ptr&lt;T&gt;::value;
}

call(&amp;Foo::func);
</code></pre>
</blockquote>
<p>führt zu:T = void (Foo::*)(int, int)</p>
<pre><code class="language-cpp">//Schritt 1:

template &lt;typename T, typename C&gt; struct is_mem_fun_ptr&lt;void (Foo::*)(int, int)&gt; : is_function&lt;void(int,int)&gt; {};
</code></pre>
<p>T = void(int,int), C = Foo</p>
<pre><code class="language-cpp">//Schritt 2:

template &lt;typename T&gt; struct is_function : is_same&lt;void(void(int,int)),void(void(*)(int,int))&gt; {};
</code></pre>
<p>Auf beiden Seiten steht jeweils eine Funktion, die void zurückliefert, und einen Zeiger auf eine Funktion nimmt, welche ihrerseits void zurückgibt und 2 int-Parameter hat. Auf der linken Seite haben wir aber nicht ausdrücklich hingeschrieben, dess es ein Zeiger ist, diese Transformation nimmt der Compiler <em>an dieser Stelle</em> automatisch vor.</p>
<p>Der obskure Fakt, dass man Funktionen so deklarieren kann, als ob sie einen Funktionsparameter hätten, ist als solches nichts, was man als normaler Programmierer beachten muss. Es taucht in C++ allerdings als Hindernis auf:<br />
falls du schon mal versucht hast, ein Objekt zu erstellen, dass mit einem default-konstruiertem anderen Objekt initialisiert werden sollte, bis du vielleicht darüber gestolpert:</p>
<pre><code class="language-cpp">struct Foo { ... }; struct Bar { ... };
...
Foo my_foo( Bar() ); // Funktionsdeklaration, keine Variablendefinition
</code></pre>
<p>noch ein Grund, Initilisierung nicht gewohnheitsmäßig mit Klammern statt = durchzuführen... :p (eine Lösungsmöglichkeit besteht in einem zusätzlichen Klammerpaar um Bar() )</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2240533</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2240533</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Thu, 09 Aug 2012 21:31:35 GMT</pubDate></item><item><title><![CDATA[Reply to Check für is member function pointer on Thu, 09 Aug 2012 21:36:41 GMT]]></title><description><![CDATA[<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/6642">@camper</a>: Ich habe jetzt deine Variante genommen und etwas veraendert. const/volatile Memberfunktionen funktionieren bei mir auch. Habe ich was uebersehen?</p>
<pre><code class="language-cpp">template &lt;bool B&gt;
struct bool_
{
	static bool const value = B;
};

typedef bool_&lt;true&gt; true_;
typedef bool_&lt;false&gt; false_;

template &lt;typename T, typename U&gt;
struct is_same
	: false_
{};

template &lt;typename T&gt;
struct is_same&lt;T, T&gt;
	: true_
{};

template &lt;typename T&gt;
struct is_function
	: is_same&lt;void(T), void(T*)&gt;
{};

template &lt;typename T&gt;
struct is_member_function_pointer
	: false_
{};

template &lt;typename T, typename C&gt;
struct is_member_function_pointer&lt;T C::*&gt;
	: is_function&lt;T&gt;
{};

///////////////////

#include &lt;iostream&gt;

struct foo
{};

int main()
{
	std::cout &lt;&lt; is_member_function_pointer&lt;void (foo::*) (int, float)&gt;::value &lt;&lt; '\n';
	std::cout &lt;&lt; is_member_function_pointer&lt;void (foo::*) (int, float) const&gt;::value &lt;&lt; '\n';
	std::cout &lt;&lt; is_member_function_pointer&lt;void (foo::*) (int, float) volatile&gt;::value &lt;&lt; '\n';
	std::cout &lt;&lt; is_member_function_pointer&lt;void (foo::*) (int, float) const volatile&gt;::value &lt;&lt; '\n';
}
</code></pre>
<p><a href="http://ideone.com/HXYhj" rel="nofollow">http://ideone.com/HXYhj</a></p>
<p>Edit: Mir faellt gerade auf, ich habe genau das gleiche wie du, nur ohne die Checks. Hab mir deinen Code nicht so genau angesehen <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 />
Trotzdem funktionierts auch mit const/volatile Memberfunktionen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2240536</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2240536</guid><dc:creator><![CDATA[Kellerautomat]]></dc:creator><pubDate>Thu, 09 Aug 2012 21:36:41 GMT</pubDate></item><item><title><![CDATA[Reply to Check für is member function pointer on Thu, 09 Aug 2012 22:20:46 GMT]]></title><description><![CDATA[<p>Kellerautomat schrieb:</p>
<blockquote>
<p>Habe ich was uebersehen?</p>
</blockquote>
<p>Nein, scheint als bin ich hier einem Irrtum aufgessen.<br />
Es ist ist nicht möglich einen bereits bestehenden Funktionstyp mit cv-Qualifikation zu versehen, als Teil des Funktionstyp existiert die Qualifikation aber durchaus:</p>
<pre><code class="language-cpp">typedef void f();
typedef void g() const; // ältere Compiler werden das u.U. verweigern
typedef const f h; // const wird ignoriert

struct foo
{
    f fun;  // deklariert void foo::fun()
    g fun;  // deklariert void foo::fun() const
    h fun;  // Fehler: Redeklaration von void foo::fun()
};
</code></pre>
<p>Umso besser: dann gibt es doch eine schöne Lösung auch in C++03.</p>
<p>wenn ich</p>
<pre><code class="language-cpp">template &lt;bool b&gt; struct bool_ { static const bool value = b; };
typedef bool_&lt;false&gt; false_type;
typedef bool_&lt;true&gt; true_type;

template &lt;typename T, typename U&gt; struct is_same : false_type {};
template &lt;typename T&gt; struct is_same&lt;T, T&gt; : true_type {};

template &lt;typename T&gt; struct is_function : is_same&lt;void(T),void(T*)&gt; {};
template &lt;&gt; struct is_function&lt;const void&gt; : false_type {};
template &lt;&gt; struct is_function&lt;volatile void&gt; : false_type {};
template &lt;&gt; struct is_function&lt;const volatile void&gt; : false_type {};
template &lt;typename T&gt; struct is_function&lt;T&amp;&gt; : false_type {};

template &lt;typename T&gt; struct is_mem_fun_ptr : false_type {};
template &lt;typename T, typename C&gt; struct is_mem_fun_ptr&lt;T C::*&gt; : is_function&lt;T&gt; {};

struct Foo { void f(); void g() const; };

template &lt;typename T&gt;
void foo(T)
{
    int dummy[is_mem_fun_ptr&lt;T&gt;::value];
}

int main()
{
    foo(&amp;Foo::f);
    foo(&amp;Foo::g);
}
</code></pre>
<p>durch <a href="http://www.comeaucomputing.com/tryitout/" rel="nofollow">Online-Comeau C++</a> jage, gibt es Fehler. g++4.6 und clang sind damit zufrieden. Evtl. sollte man noch ältere Versionen von g++ und Visual C++ testen. Mir ist allerdings auch nicht bewusst, dass es hier eine Änderung in C++11 gegeben hätte. Ich bin allerdings auch ziemlich sicher, dass das früher nicht so funktioniert hat.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2240539</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2240539</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Thu, 09 Aug 2012 22:20:46 GMT</pubDate></item><item><title><![CDATA[Reply to Check für is member function pointer on Fri, 10 Aug 2012 18:33:58 GMT]]></title><description><![CDATA[<p>Also in VS2008 wird mit eurem code eine const member funktion nicht erkannt.<br />
Kann man noch irgendwo eine Spezialisierung einbauen, so das es funktioniert?</p>
<p>Das der compiler das so hier auflöst hätte ich nicht gedacht.</p>
<pre><code class="language-cpp">template &lt;typename T, typename C&gt; struct is_mem_fun_ptr&lt;void (Foo::*)(int, int)&gt; : is_function&lt;void(int,int)&gt; {};
</code></pre>
<p>Mit ist leider immer noch einiges nicht klar:</p>
<pre><code class="language-cpp">template &lt;typename T, typename C&gt; struct is_mem_fun_ptr&lt;T C::*&gt; : is_function&lt;T&gt; {};
</code></pre>
<p>Für welchen Typ T wird dieses template instanziert, obwohl es keine member function ist?<br />
Durch <strong>T C::</strong>* kann es doch eigentlich nur für member functions aufgerufen werden.</p>
<p>So das dann der nachfolgende Test mit is_function überhaupt nocht sinn macht.</p>
<p>jetzt zu dem Konstrukt:</p>
<pre><code class="language-cpp">template &lt;typename T&gt; struct is_function : is_same&lt;void(void(int,int)),void(void(*)(int,int))&gt; {};
</code></pre>
<p>Auf der linken Seite deklarierst du einen Funktionszeiger, dieser wird durch den compiler <strong>nochmal</strong> <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="😕"
    /> zu einem Funktionszeiger transformiert? Auf der rechten Seite machen wir das manuell. Ist das so korrekt?</p>
<p>PS: wo lernt man solche Tricks mit</p>
<blockquote>
<p>is_same&lt;void(T),void(T*)&gt; {};</p>
</blockquote>
<p>?<br />
Also das wäre mit nicht im traum eingefallen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2240818</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2240818</guid><dc:creator><![CDATA[Nash26]]></dc:creator><pubDate>Fri, 10 Aug 2012 18:33:58 GMT</pubDate></item><item><title><![CDATA[Reply to Check für is member function pointer on Fri, 10 Aug 2012 18:27:56 GMT]]></title><description><![CDATA[<p>Nash26 schrieb:</p>
<blockquote>
<pre><code class="language-cpp">template &lt;typename T, typename C&gt; struct is_mem_fun_ptr&lt;T C::*&gt; : is_function&lt;T&gt; {};
</code></pre>
<p>Für welchen Typ T wird dieses template instanziert, obwohl es keine member function ist?</p>
</blockquote>
<p>Wenn der Parameter nicht auf diese Spezialisierung passt, wird das Default-Template genommen:</p>
<pre><code class="language-cpp">template &lt;typename T&gt; struct is_mem_fun_ptr : false_type {};
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2240822</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2240822</guid><dc:creator><![CDATA[wxSkip]]></dc:creator><pubDate>Fri, 10 Aug 2012 18:27:56 GMT</pubDate></item><item><title><![CDATA[Reply to Check für is member function pointer on Fri, 10 Aug 2012 18:35:10 GMT]]></title><description><![CDATA[<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/23670">@wxSkip</a><br />
das heißt also ich kann direkt</p>
<pre><code class="language-cpp">template &lt;typename T, typename C&gt; struct is_mem_fun_ptr&lt;T C::*&gt; : true_type {};
</code></pre>
<p>schreiben?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2240828</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2240828</guid><dc:creator><![CDATA[Nash26]]></dc:creator><pubDate>Fri, 10 Aug 2012 18:35:10 GMT</pubDate></item><item><title><![CDATA[Reply to Check für is member function pointer on Fri, 10 Aug 2012 18:40:42 GMT]]></title><description><![CDATA[<p>Nash26 schrieb:</p>
<blockquote>
<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/23670">@wxSkip</a><br />
das heißt also ich kann direkt</p>
<pre><code class="language-cpp">template &lt;typename T, typename C&gt; struct is_mem_fun_ptr&lt;T C::*&gt; : true_type {};
</code></pre>
<p>schreiben?</p>
</blockquote>
<p>Nein. Es gibt auch Nicht-Memberfunktions-Typen, die auf diese Spezialisierung passen. Und zwar sind das die relativ unbekannten Zeiger auf Member. Wenn du eine Klasse mit verschiedenen Variablen hast, kannst du einen Zeiger auf eine Klassenvariable holen, der praktisch die interne Position in der Klasse speichert. Wenn du dann noch ein konkretes Objekt hast, kannst du mit diesem Zeiger auf die Variable dieses Objektes zugreifen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2240829</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2240829</guid><dc:creator><![CDATA[wxSkip]]></dc:creator><pubDate>Fri, 10 Aug 2012 18:40:42 GMT</pubDate></item><item><title><![CDATA[Reply to Check für is member function pointer on Fri, 10 Aug 2012 21:26:13 GMT]]></title><description><![CDATA[<p>Nash26 schrieb:</p>
<blockquote>
<p>jetzt zu dem Konstrukt:</p>
<pre><code class="language-cpp">template &lt;typename T&gt; struct is_function : is_same&lt;void(void(int,int)),void(void(*)(int,int))&gt; {};
</code></pre>
<p>Auf der linken Seite deklarierst du einen Funktionszeiger, dieser wird durch den compiler <strong>nochmal</strong> <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="😕"
    /> zu einem Funktionszeiger transformiert? Auf der rechten Seite machen wir das manuell. Ist das so korrekt?</p>
</blockquote>
<p>Links wird ein Funktionstyp deklariert, rechts wird ein Funktionstyp deklariert. Beiden Typen haben ihrerseits einen Funktionszeiger <em>als Parametertyp</em>.</p>
<p>Nash26 schrieb:</p>
<blockquote>
<p>PS: wo lernt man solche Tricks mit</p>
<blockquote>
<p>is_same&lt;void(T),void(T*)&gt; {};</p>
</blockquote>
<p>?<br />
Also das wäre mit nicht im traum eingefallen.</p>
</blockquote>
<p>Den Trick als solchen habe ich mir on-the-fly beim Schreiben ausgedacht. Den zugrunde liegenden Mechanismus lernt man irgendwann nebenbei kennen, wenn es um etwas ganz anderes geht.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2240872</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2240872</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Fri, 10 Aug 2012 21:26:13 GMT</pubDate></item><item><title><![CDATA[Reply to Check für is member function pointer on Fri, 10 Aug 2012 21:42:06 GMT]]></title><description><![CDATA[<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/6642">@camper</a><br />
tja bleibt nur noch die Frage warum es mit VS2008 nicht mit const methoden klappt.<br />
Hast du einen workaround dafür?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2240876</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2240876</guid><dc:creator><![CDATA[Nash26]]></dc:creator><pubDate>Fri, 10 Aug 2012 21:42:06 GMT</pubDate></item><item><title><![CDATA[Reply to Check für is member function pointer on Sun, 12 Aug 2012 11:40:23 GMT]]></title><description><![CDATA[<p>ich bekomme es einfach nicht hin:</p>
<pre><code class="language-cpp">template &lt;typename T, typename C&gt; struct is_mem_fun_ptr&lt;T const C::*&gt; : is_function&lt;T&gt; {};
</code></pre>
<p>wenn ich das template mit einer const member function aufrufe wird sofort:</p>
<pre><code class="language-cpp">template &lt;typename T&gt; struct is_mem_fun_ptr : false_type {};
</code></pre>
<p>instanziiert</p>
<p>auch den const qualifier zu entfernen klappt nicht.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2241168</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2241168</guid><dc:creator><![CDATA[Nash26]]></dc:creator><pubDate>Sun, 12 Aug 2012 11:40:23 GMT</pubDate></item><item><title><![CDATA[Reply to Check für is member function pointer on Sun, 12 Aug 2012 17:59:20 GMT]]></title><description><![CDATA[<p>Nash26 schrieb:</p>
<blockquote>
<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/6642">@camper</a><br />
tja bleibt nur noch die Frage warum es mit VS2008 nicht mit const methoden klappt.<br />
Hast du einen workaround dafür?</p>
</blockquote>
<p>Nein. Es gilt dann einfach das, was ich zuerst gesagt habe.</p>
<p>Nash26 schrieb:</p>
<blockquote>
<p>ich bekomme es einfach nicht hin:</p>
<pre><code class="language-cpp">template &lt;typename T, typename C&gt; struct is_mem_fun_ptr&lt;T const C::*&gt; : is_function&lt;T&gt; {};
</code></pre>
<p>wenn ich das template mit einer const member function aufrufe wird sofort:</p>
<pre><code class="language-cpp">template &lt;typename T&gt; struct is_mem_fun_ptr : false_type {};
</code></pre>
<p>instanziiert</p>
<p>auch den const qualifier zu entfernen klappt nicht.</p>
</blockquote>
<p>Das ist kein Wunder.<br />
Einen const/volatile-Qualifizierer zu einem Funktionstyp hinzuzufügen macht daraus gerade keinen const/volatile-Funktionstyp, je nach Kontext ist es schlicht illegal oder wird ignoriert.</p>
<p>Die Spezialisierung</p>
<pre><code class="language-cpp">template &lt;typename T, typename C&gt; struct is_mem_fun_ptr&lt;T const C::*&gt; : is_function&lt;T&gt; {};
</code></pre>
<p>würde folglich nur für Zeiger auf konstante Member (also vor allem keine Memberfunktionen) genutzt werden.</p>
<p>boost.type_traits hat bereits eine portable Lösung. Ich kann keine Bessere anbieten.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2241242</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2241242</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Sun, 12 Aug 2012 17:59:20 GMT</pubDate></item><item><title><![CDATA[Reply to Check für is member function pointer on Sun, 12 Aug 2012 18:51:26 GMT]]></title><description><![CDATA[<p>du hattest geschrieben</p>
<blockquote>
<p>Das Testen auf non-const-non-volatile-Memberfunktionszeiger ist einfach. Schwierigkeiten machen nur const,volatile und const volatile-Memberfunktionen:</p>
</blockquote>
<p>das heißt also, es gibt für VS2008 nur die Möglichkeit auf viele Spezialiserungen zu testen? Korrekt?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2241267</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2241267</guid><dc:creator><![CDATA[Nash26]]></dc:creator><pubDate>Sun, 12 Aug 2012 18:51:26 GMT</pubDate></item><item><title><![CDATA[Reply to Check für is member function pointer on Sun, 12 Aug 2012 21:22:45 GMT]]></title><description><![CDATA[<p>Nash26 schrieb:</p>
<blockquote>
<p>du hattest geschrieben</p>
<blockquote>
<p>Das Testen auf non-const-non-volatile-Memberfunktionszeiger ist einfach. Schwierigkeiten machen nur const,volatile und const volatile-Memberfunktionen:</p>
</blockquote>
<p>das heißt also, es gibt für VS2008 nur die Möglichkeit auf viele Spezialiserungen zu testen? Korrekt?</p>
</blockquote>
<p>Das, oder Ausschlussverfahren</p>
<pre><code>#include &lt;cstddef&gt;

template &lt;bool b&gt; struct bool_ { static const bool value = b; };
template &lt;typename T&gt; struct not_ { static const bool value = !T::value; };
typedef bool_&lt;true&gt; true_type;
typedef bool_&lt;false&gt; false_type;

template &lt;typename T&gt; struct identity { typedef T type; };

// is_same
template &lt;typename T, typename U&gt; struct is_same : false_type {};
template &lt;typename T&gt; struct is_same&lt;T, T&gt; : true_type {};

// add_reference
template &lt;typename T&gt; struct add_reference : identity&lt;T&amp;&gt; {};
template &lt;typename T&gt; struct add_reference&lt;T&amp;&gt; : identity&lt;T&amp;&gt; {};

// remove_reference (funktioniert auch mit rvalue-Referenzen)
template &lt;typename T&gt; struct remove_reference : remove_reference&lt;typename add_reference&lt;T&gt;::type&gt; {};
template &lt;typename T&gt; struct remove_reference&lt;T&amp;&gt; : identity&lt;T&gt; {};

// is_reference (funktioniert auch mit rvalue-Referenzen)
template &lt;typename T&gt; struct is_reference : not_&lt;is_same&lt;T, typename remove_reference&lt;typename add_reference&lt;T&gt;::type&gt;::type&gt; &gt; {};

// is_pointer
template &lt;typename T&gt; struct is_pointer : false_type {};
template &lt;typename T&gt; struct is_pointer&lt;T*&gt; : true_type {};

// is_class (class/struct/union)
template &lt;typename T&gt; struct is_class
{
    typedef char&amp; yes_type;
    typedef char (&amp;no_type)[2];
    template &lt;typename U&gt; static no_type test(...);
    template &lt;typename U&gt; static yes_type test(int U::*);
    static const bool value = sizeof test&lt;T&gt;(0) == sizeof(yes_type);
};

// is_array
template &lt;typename T&gt; struct is_array : false_type {};
template &lt;typename T&gt; struct is_array&lt;T[]&gt; : true_type {};
template &lt;typename T, std::size_t N&gt; struct is_array&lt;T[N]&gt; : true_type {};

// is_void
template &lt;typename T&gt; struct is_void : false_type {};
template &lt;&gt; struct is_void&lt;void&gt; : true_type {};
template &lt;&gt; struct is_void&lt;const void&gt; : true_type {};
template &lt;&gt; struct is_void&lt;volatile void&gt; : true_type {};
template &lt;&gt; struct is_void&lt;const volatile void&gt; : true_type {};

// is_function
template &lt;typename T, bool = !is_void&lt;T&gt;::value &amp;&amp; !is_reference&lt;T&gt;::value&gt; struct is_function : is_same&lt;void(T),void(T*)&gt; {};
template &lt;typename T&gt; struct is_function&lt;T, false&gt; : false_type {};

// is_convertible
template &lt;typename T, typename U&gt; struct is_convertible
{
    static typename add_reference&lt;T&gt;::type makeT();
    typedef char&amp; yes_type;
    typedef char (&amp;no_type)[2];
    static no_type test(...);
    static yes_type test(U);
    static const bool value = sizeof test(makeT()) == sizeof(yes_type);
};

// is_convertible_static
template &lt;typename T, typename U&gt; struct is_convertible_static
{
    static typename add_reference&lt;T&gt;::type makeT();
    typedef char&amp; yes_type;
    typedef char (&amp;no_type)[2];
    template &lt;typename V&gt; static no_type test(...);
    template &lt;typename V&gt; static yes_type test(char(*)[sizeof(static_cast&lt;V&gt;(makeT()))]);
    static const bool value = sizeof test&lt;U&gt;(0) == sizeof(yes_type);
};

// is_fundamental_or_enum (including scoped enums)
template &lt;typename T&gt; struct is_fundamental_or_enum : bool_&lt;is_void&lt;T&gt;::value || ( !is_class&lt;T&gt;::value &amp;&amp; !is_reference&lt;T&gt;::value &amp;&amp; is_convertible_static&lt;T, int&gt;::value )&gt; {};

// is_mem_data_ptr
template &lt;typename T&gt; struct is_mem_data_ptr : false_type {};
template &lt;typename T, typename C&gt; struct is_mem_data_ptr&lt;T C::*&gt; : not_&lt;is_function&lt;T&gt; &gt; {};

// is_mem_fun_ptr
template &lt;typename T&gt; struct is_mem_fun_ptr : bool_&lt;!is_fundamental_or_enum&lt;T&gt;::value &amp;&amp; !is_class&lt;T&gt;::value &amp;&amp; !is_pointer&lt;T&gt;::value &amp;&amp; !is_reference&lt;T&gt;::value
                                                    &amp;&amp; !is_function&lt;T&gt;::value &amp;&amp; !is_array&lt;T&gt;::value &amp;&amp; !is_mem_data_ptr&lt;T&gt;::value&gt; {};

#include &lt;iostream&gt;

enum A { a, b, c };
enum class B { d, e, f };
struct C {};
union D {};

int main()
{
    using std::cout;
    cout &lt;&lt; &quot;\t\t\tint\tint&amp;\tint&amp;&amp;\tint[6]\tint*\tint()\tint(*)();int(&amp;)();enum A;ec B\tstructC\tunionD\tint D::*;int(D::*)();int(D::*)const\n&quot;;
    cout &lt;&lt; &quot;is_reference\t&quot; &lt;&lt; '\t';
    cout &lt;&lt; is_reference&lt;int&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_reference&lt;int&amp;&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_reference&lt;int&amp;&amp;&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_reference&lt;int[6]&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_reference&lt;int*&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_reference&lt;int()&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_reference&lt;int(*)()&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_reference&lt;int(&amp;)()&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_reference&lt;A&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_reference&lt;B&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_reference&lt;C&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_reference&lt;D&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_reference&lt;int D::*&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_reference&lt;int (D::*)()&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_reference&lt;int (D::*)()const&gt;::value &lt;&lt; '\n';

    cout &lt;&lt; &quot;is_array\t&quot; &lt;&lt; '\t';
    cout &lt;&lt; is_array&lt;int&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_array&lt;int&amp;&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_array&lt;int&amp;&amp;&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_array&lt;int[6]&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_array&lt;int*&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_array&lt;int()&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_array&lt;int(*)()&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_array&lt;int(&amp;)()&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_array&lt;A&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_array&lt;B&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_array&lt;C&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_array&lt;D&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_array&lt;int D::*&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_array&lt;int (D::*)()&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_array&lt;int (D::*)()const&gt;::value &lt;&lt; '\n';

    cout &lt;&lt; &quot;is_pointer\t&quot; &lt;&lt; '\t';
    cout &lt;&lt; is_pointer&lt;int&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_pointer&lt;int&amp;&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_pointer&lt;int&amp;&amp;&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_pointer&lt;int[6]&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_pointer&lt;int*&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_pointer&lt;int()&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_pointer&lt;int(*)()&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_pointer&lt;int(&amp;)()&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_pointer&lt;A&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_pointer&lt;B&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_pointer&lt;C&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_pointer&lt;D&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_pointer&lt;int D::*&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_pointer&lt;int (D::*)()&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_pointer&lt;int (D::*)()const&gt;::value &lt;&lt; '\n';

    cout &lt;&lt; &quot;is_function\t&quot; &lt;&lt; '\t';
    cout &lt;&lt; is_function&lt;int&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_function&lt;int&amp;&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_function&lt;int&amp;&amp;&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_function&lt;int[6]&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_function&lt;int*&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_function&lt;int()&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_function&lt;int(*)()&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_function&lt;int(&amp;)()&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_function&lt;A&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_function&lt;B&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_function&lt;C&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_function&lt;D&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_function&lt;int D::*&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_function&lt;int (D::*)()&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_function&lt;int (D::*)()const&gt;::value &lt;&lt; '\n';

    cout &lt;&lt; &quot;is_class\t&quot; &lt;&lt; '\t';
    cout &lt;&lt; is_class&lt;int&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_class&lt;int&amp;&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_class&lt;int&amp;&amp;&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_class&lt;int[6]&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_class&lt;int*&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_class&lt;int()&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_class&lt;int(*)()&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_class&lt;int(&amp;)()&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_class&lt;A&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_class&lt;B&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_class&lt;C&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_class&lt;D&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_class&lt;int D::*&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_class&lt;int (D::*)()&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_class&lt;int (D::*)()const&gt;::value &lt;&lt; '\n';

    cout &lt;&lt; &quot;is_fund_or_enum\t&quot; &lt;&lt; '\t';
    cout &lt;&lt; is_fundamental_or_enum&lt;int&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_fundamental_or_enum&lt;int&amp;&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_fundamental_or_enum&lt;int&amp;&amp;&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_fundamental_or_enum&lt;int[6]&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_fundamental_or_enum&lt;int*&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_fundamental_or_enum&lt;int()&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_fundamental_or_enum&lt;int(*)()&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_fundamental_or_enum&lt;int(&amp;)()&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_fundamental_or_enum&lt;A&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_fundamental_or_enum&lt;B&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_fundamental_or_enum&lt;C&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_fundamental_or_enum&lt;D&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_fundamental_or_enum&lt;int D::*&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_fundamental_or_enum&lt;int (D::*)()&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_fundamental_or_enum&lt;int (D::*)()const&gt;::value &lt;&lt; '\n';

    cout &lt;&lt; &quot;is_mem_data_ptr\t&quot; &lt;&lt; '\t';
    cout &lt;&lt; is_mem_data_ptr&lt;int&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_mem_data_ptr&lt;int&amp;&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_mem_data_ptr&lt;int&amp;&amp;&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_mem_data_ptr&lt;int[6]&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_mem_data_ptr&lt;int*&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_mem_data_ptr&lt;int()&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_mem_data_ptr&lt;int(*)()&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_mem_data_ptr&lt;int(&amp;)()&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_mem_data_ptr&lt;A&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_mem_data_ptr&lt;B&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_mem_data_ptr&lt;C&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_mem_data_ptr&lt;D&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_mem_data_ptr&lt;int D::*&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_mem_data_ptr&lt;int (D::*)()&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_mem_data_ptr&lt;int (D::*)()const&gt;::value &lt;&lt; '\n';

    cout &lt;&lt; &quot;is_mem_fun_ptr\t&quot; &lt;&lt; '\t';
    cout &lt;&lt; is_mem_fun_ptr&lt;int&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_mem_fun_ptr&lt;int&amp;&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_mem_fun_ptr&lt;int&amp;&amp;&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_mem_fun_ptr&lt;int[6]&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_mem_fun_ptr&lt;int*&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_mem_fun_ptr&lt;int()&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_mem_fun_ptr&lt;int(*)()&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_mem_fun_ptr&lt;int(&amp;)()&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_mem_fun_ptr&lt;A&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_mem_fun_ptr&lt;B&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_mem_fun_ptr&lt;C&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_mem_fun_ptr&lt;D&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_mem_fun_ptr&lt;int D::*&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_mem_fun_ptr&lt;int (D::*)()&gt;::value &lt;&lt; '\t';
    cout &lt;&lt; is_mem_fun_ptr&lt;int (D::*)()const&gt;::value &lt;&lt; '\n';
}
</code></pre>
<p>sollte funktionieren (rvalue-Rereferenzen bei alten Compilern weglassen).</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2241298</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2241298</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Sun, 12 Aug 2012 21:22:45 GMT</pubDate></item><item><title><![CDATA[Reply to Check für is member function pointer on Mon, 13 Aug 2012 22:28:51 GMT]]></title><description><![CDATA[<p>Nochmal ein bisschen überarbeitet. Diese Version funktioniert mindestens ab gcc 3.4, Comeau-C++ und clang 3.1 sind auch zufrieden.<br />
rvalue-Referenzen und scoped enums werden unterstützt, es werden aber keine C++11-Features verwendet. Es sollte auch mit extended integer Typen funktionieren, allerdings kann ich das nicht testen.<br />
Was sagt Visual C++ dazu?</p>
<pre><code>#include &lt;cstddef&gt;

template &lt;bool b&gt; struct bool_ { static const bool value = b; };
template &lt;typename T&gt; struct not_ { static const bool value = !T::value; };
typedef bool_&lt;true&gt; true_type;
typedef bool_&lt;false&gt; false_type;

template &lt;typename T&gt; struct identity { typedef T type; };

template &lt;typename T&gt; struct is_void;
template &lt;typename T&gt; struct is_array;
template &lt;typename T, bool = is_void&lt;T&gt;::value || is_array&lt;T&gt;::value&gt; struct is_reference;
template &lt;typename T&gt; struct is_class;

// transformations
template &lt;typename T, bool = is_void&lt;T&gt;::value&gt; struct add_reference : identity&lt;T&amp;&gt; {};
template &lt;typename T, bool b&gt; struct add_reference&lt;T&amp;, b&gt; : identity&lt;T&amp;&gt; {};
template &lt;typename T&gt; struct add_reference&lt;T, true&gt; : identity&lt;T&gt; {};

template &lt;typename T, bool = is_void&lt;T&gt;::value&gt; struct remove_reference : remove_reference&lt;typename add_reference&lt;T&gt;::type&gt; {};
template &lt;typename T, bool b&gt; struct remove_reference&lt;T&amp;, b&gt; : identity&lt;T&gt; {};
template &lt;typename T&gt; struct remove_reference&lt;T, true&gt; : identity&lt;T&gt; {};

template &lt;typename T&gt; struct remove_const : identity&lt;T&gt; {};
template &lt;typename T&gt; struct remove_const&lt;const T&gt; : identity&lt;T&gt; {};

template &lt;typename T&gt; struct remove_volatile : identity&lt;T&gt; {};
template &lt;typename T&gt; struct remove_volatile&lt;volatile T&gt; : identity&lt;T&gt; {};

template &lt;typename T&gt; struct remove_cv : remove_volatile&lt;typename remove_const&lt;T&gt;::type&gt; {};

// relations
template &lt;typename T, typename U&gt; struct is_same : false_type {};
template &lt;typename T&gt; struct is_same&lt;T, T&gt; : true_type {};

template &lt;typename T, typename U, bool = is_void&lt;T&gt;::value&gt; struct is_convertible
{
    static typename add_reference&lt;T&gt;::type makeT();
    typedef char&amp; yes_type;
    typedef char (&amp;no_type)[2];
    template &lt;typename V&gt; static no_type test(...);
    template &lt;typename V&gt; static yes_type test(V);
    static const bool value = sizeof test&lt;U&gt;(makeT()) == sizeof(yes_type);
};
template &lt;typename T, typename U&gt; struct is_convertible&lt;T[], U, false&gt; : is_convertible&lt;T*, U, false&gt; {};
template &lt;typename T, std::size_t N, typename U&gt; struct is_convertible&lt;T[N], U, false&gt; : is_convertible&lt;T*, U, false&gt; {};
template &lt;typename T, typename U&gt; struct is_convertible&lt;T, U, true&gt; : is_void&lt;U&gt; {};

// predicates
template &lt;typename T&gt; struct is_void : is_same&lt;typename remove_cv&lt;T&gt;::type, void&gt; {};

template &lt;typename T&gt; struct is_arithmetic : bool_&lt;!is_class&lt;T&gt;::value &amp;&amp; !is_reference&lt;T&gt;::value &amp;&amp; is_convertible&lt;T, int&gt;::value &amp;&amp; is_convertible&lt;int, T&gt;::value&gt; {};

template &lt;typename T&gt; struct is_fundamental: bool_&lt;is_arithmetic&lt;T&gt;::value || is_void&lt;T&gt;::value&gt; {};

template &lt;typename T&gt; struct is_array : false_type {};
template &lt;typename T&gt; struct is_array&lt;T[]&gt; : true_type {};
template &lt;typename T, std::size_t N&gt; struct is_array&lt;T[N]&gt; : true_type {};

template &lt;typename T, bool = !is_void&lt;T&gt;::value &amp;&amp; !is_reference&lt;T&gt;::value &amp;&amp; !is_array&lt;T&gt;::value&gt; struct is_function : is_same&lt;void(T),void(T*)&gt; {};
template &lt;typename T&gt; struct is_function&lt;T, false&gt; : false_type {};

template &lt;typename T&gt; struct is_object : bool_&lt;!is_void&lt;T&gt;::value &amp;&amp; !is_reference&lt;T&gt;::value &amp;&amp; !is_function&lt;T&gt;::value&gt; {};

template &lt;typename T&gt; struct is_pointer : false_type {};
template &lt;typename T&gt; struct is_pointer&lt;T*&gt; : true_type {};

template &lt;typename T, bool&gt; struct is_reference : not_&lt;is_same&lt;T, typename remove_reference&lt;typename add_reference&lt;T&gt;::type&gt;::type&gt; &gt; {};
template &lt;typename T&gt; struct is_reference&lt;T, true&gt; : false_type {};

template &lt;typename T&gt; struct is_class
{
    typedef char&amp; yes_type;
    typedef char (&amp;no_type)[2];
    template &lt;typename U&gt; static no_type test(...);
    template &lt;typename U&gt; static yes_type test(int U::*);
    static const bool value = sizeof test&lt;T&gt;(0) == sizeof(yes_type);
};

template &lt;typename T&gt; struct is_unscoped_enum : bool_&lt;is_object&lt;T&gt;::value &amp;&amp; !is_fundamental&lt;T&gt;::value &amp;&amp; !is_class&lt;T&gt;::value &amp;&amp; is_convertible&lt;T, int&gt;::value&gt; {};

template &lt;typename T, bool = is_object&lt;T&gt;::value &amp;&amp; !is_class&lt;T&gt;::value &amp;&amp; !is_fundamental&lt;T&gt;::value &amp;&amp; !is_array&lt;T&gt;::value
                             &amp;&amp; !is_pointer&lt;T&gt;::value &amp;&amp; !is_unscoped_enum&lt;T&gt;::value&gt;
struct is_scoped_enum : not_&lt;is_convertible&lt;T, bool&gt; &gt; {};
template &lt;typename T&gt; struct is_scoped_enum&lt;T, false&gt; : false_type {};

template &lt;typename T&gt; struct is_enum : bool_&lt;is_unscoped_enum&lt;T&gt;::value || is_scoped_enum&lt;T&gt;::value&gt; {};

template &lt;typename T&gt; struct is_mem_data_ptr : false_type {};
template &lt;typename T, typename C&gt; struct is_mem_data_ptr&lt;T C::*&gt; : is_object&lt;typename remove_reference&lt;T&gt;::type&gt; {};

template &lt;typename T&gt; struct is_mem_fun_ptr : bool_&lt;is_object&lt;T&gt;::value &amp;&amp; !is_class&lt;T&gt;::value &amp;&amp; !is_fundamental&lt;T&gt;::value &amp;&amp; !is_array&lt;T&gt;::value
						    &amp;&amp; !is_pointer&lt;T&gt;::value &amp;&amp; !is_enum&lt;T&gt;::value &amp;&amp; !is_mem_data_ptr&lt;T&gt;::value&gt; {};

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template &lt;bool b&gt; struct assertion_failure;
template &lt;&gt; struct assertion_failure&lt;true&gt; : true_type {};

#define FUSE( x, y ) x##y
#define STATIC_ASSERT( T, x, v ) typedef int FUSE( assert, __LINE__ ) [sizeof(assertion_failure&lt;T&lt;x&gt;::value==v&gt;::value)]

typedef int arithmetic_type;
typedef void void_type;
typedef int&amp; lref_type;
typedef int array_type[42];
typedef int array_type2[];
typedef int***** pointer_type;
typedef int fun_type();
typedef int(*pfun_type)();
typedef int(&amp;fun_ref_type)();
enum enum_type {};
struct struct_type {};
union union_type {};
typedef enum_type (struct_type::*mem_data_ptr_type_helper)() const;
typedef mem_data_ptr_type_helper struct_type::*mem_data_ptr_type;
typedef enum_type (struct_type::*mem_fun_ptr_type_)();
typedef mem_data_ptr_type (struct_type::*mem_fun_ptr_type)() const;
typedef mem_fun_ptr_type_ (struct_type::*mem_fun_ptr_type2)() const;

#ifdef WITHCPP11
enum class enum_class_type {};
#define ENUM_CLASS_IS_SCOPED true
typedef int&amp;&amp; rref_type;
#else
enum enum_class_type {};
#define ENUM_CLASS_IS_SCOPED false
typedef int&amp; rref_type;
#endif

int main()
{
    STATIC_ASSERT( is_class, arithmetic_type,   false );
    STATIC_ASSERT( is_class, void_type,         false );
    STATIC_ASSERT( is_class, lref_type,         false );
    STATIC_ASSERT( is_class, rref_type,         false );
    STATIC_ASSERT( is_class, array_type,        false );
    STATIC_ASSERT( is_class, array_type2,       false );
    STATIC_ASSERT( is_class, pointer_type,      false );
    STATIC_ASSERT( is_class, fun_type,          false );
    STATIC_ASSERT( is_class, pfun_type,         false );
    STATIC_ASSERT( is_class, fun_ref_type,      false );
    STATIC_ASSERT( is_class, enum_type,         false );
    STATIC_ASSERT( is_class, enum_class_type,   false );
    STATIC_ASSERT( is_class, struct_type,       true );
    STATIC_ASSERT( is_class, union_type,        true );
    STATIC_ASSERT( is_class, mem_data_ptr_type, false );
    STATIC_ASSERT( is_class, mem_fun_ptr_type,  false );
    STATIC_ASSERT( is_class, mem_fun_ptr_type2, false );

    STATIC_ASSERT( is_arithmetic, arithmetic_type,   true );
    STATIC_ASSERT( is_arithmetic, void_type,         false );
    STATIC_ASSERT( is_arithmetic, lref_type,         false );
    STATIC_ASSERT( is_arithmetic, rref_type,         false );
    STATIC_ASSERT( is_arithmetic, array_type,        false );
    STATIC_ASSERT( is_arithmetic, array_type2,       false );
    STATIC_ASSERT( is_arithmetic, pointer_type,      false );
    STATIC_ASSERT( is_arithmetic, fun_type,          false );
    STATIC_ASSERT( is_arithmetic, pfun_type,         false );
    STATIC_ASSERT( is_arithmetic, fun_ref_type,      false );
    STATIC_ASSERT( is_arithmetic, enum_type,         false );
    STATIC_ASSERT( is_arithmetic, enum_class_type,   false );
    STATIC_ASSERT( is_arithmetic, struct_type,       false);
    STATIC_ASSERT( is_arithmetic, union_type,        false);
    STATIC_ASSERT( is_arithmetic, mem_data_ptr_type, false );
    STATIC_ASSERT( is_arithmetic, mem_fun_ptr_type,  false );
    STATIC_ASSERT( is_arithmetic, mem_fun_ptr_type2, false );

    STATIC_ASSERT( is_void, arithmetic_type,   false );
    STATIC_ASSERT( is_void, void_type,         true );
    STATIC_ASSERT( is_void, lref_type,         false );
    STATIC_ASSERT( is_void, rref_type,         false );
    STATIC_ASSERT( is_void, array_type,        false );
    STATIC_ASSERT( is_void, array_type2,       false );
    STATIC_ASSERT( is_void, pointer_type,      false );
    STATIC_ASSERT( is_void, fun_type,          false );
    STATIC_ASSERT( is_void, pfun_type,         false );
    STATIC_ASSERT( is_void, fun_ref_type,      false );
    STATIC_ASSERT( is_void, enum_type,         false );
    STATIC_ASSERT( is_void, enum_class_type,   false );
    STATIC_ASSERT( is_void, struct_type,       false );
    STATIC_ASSERT( is_void, union_type,        false );
    STATIC_ASSERT( is_void, mem_data_ptr_type, false );
    STATIC_ASSERT( is_void, mem_fun_ptr_type,  false );
    STATIC_ASSERT( is_void, mem_fun_ptr_type2, false );

    STATIC_ASSERT( is_fundamental, arithmetic_type,   true );
    STATIC_ASSERT( is_fundamental, void_type,         true );
    STATIC_ASSERT( is_fundamental, lref_type,         false );
    STATIC_ASSERT( is_fundamental, rref_type,         false );
    STATIC_ASSERT( is_fundamental, array_type,        false );
    STATIC_ASSERT( is_fundamental, array_type2,       false );
    STATIC_ASSERT( is_fundamental, pointer_type,      false );
    STATIC_ASSERT( is_fundamental, fun_type,          false );
    STATIC_ASSERT( is_fundamental, pfun_type,         false );
    STATIC_ASSERT( is_fundamental, fun_ref_type,      false );
    STATIC_ASSERT( is_fundamental, enum_type,         false );
    STATIC_ASSERT( is_fundamental, enum_class_type,   false );
    STATIC_ASSERT( is_fundamental, struct_type,       false );
    STATIC_ASSERT( is_fundamental, union_type,        false );
    STATIC_ASSERT( is_fundamental, mem_data_ptr_type, false );
    STATIC_ASSERT( is_fundamental, mem_fun_ptr_type,  false );
    STATIC_ASSERT( is_fundamental, mem_fun_ptr_type2, false );

    STATIC_ASSERT( is_array, arithmetic_type,   false );
    STATIC_ASSERT( is_array, void_type,         false );
    STATIC_ASSERT( is_array, lref_type,         false );
    STATIC_ASSERT( is_array, rref_type,         false );
    STATIC_ASSERT( is_array, array_type,        true );
    STATIC_ASSERT( is_array, array_type2,       true );
    STATIC_ASSERT( is_array, pointer_type,      false );
    STATIC_ASSERT( is_array, fun_type,          false );
    STATIC_ASSERT( is_array, pfun_type,         false );
    STATIC_ASSERT( is_array, fun_ref_type,      false );
    STATIC_ASSERT( is_array, enum_type,         false );
    STATIC_ASSERT( is_array, enum_class_type,   false );
    STATIC_ASSERT( is_array, struct_type,       false );
    STATIC_ASSERT( is_array, union_type,        false );
    STATIC_ASSERT( is_array, mem_data_ptr_type, false );
    STATIC_ASSERT( is_array, mem_fun_ptr_type,  false );
    STATIC_ASSERT( is_array, mem_fun_ptr_type2, false );

    STATIC_ASSERT( is_reference, arithmetic_type,   false );
    STATIC_ASSERT( is_reference, void_type,         false );
    STATIC_ASSERT( is_reference, lref_type,         true );
    STATIC_ASSERT( is_reference, rref_type,         true );
    STATIC_ASSERT( is_reference, array_type,        false );
    STATIC_ASSERT( is_reference, array_type2,       false );
    STATIC_ASSERT( is_reference, pointer_type,      false );
    STATIC_ASSERT( is_reference, fun_type,          false );
    STATIC_ASSERT( is_reference, pfun_type,         false );
    STATIC_ASSERT( is_reference, fun_ref_type,      true );
    STATIC_ASSERT( is_reference, enum_type,         false );
    STATIC_ASSERT( is_reference, enum_class_type,   false );
    STATIC_ASSERT( is_reference, struct_type,       false );
    STATIC_ASSERT( is_reference, union_type,        false );
    STATIC_ASSERT( is_reference, mem_data_ptr_type, false );
    STATIC_ASSERT( is_reference, mem_fun_ptr_type,  false );
    STATIC_ASSERT( is_reference, mem_fun_ptr_type2, false );

    STATIC_ASSERT( is_pointer, arithmetic_type,   false );
    STATIC_ASSERT( is_pointer, void_type,         false );
    STATIC_ASSERT( is_pointer, lref_type,         false );
    STATIC_ASSERT( is_pointer, rref_type,         false );
    STATIC_ASSERT( is_pointer, array_type,        false );
    STATIC_ASSERT( is_pointer, array_type2,       false );
    STATIC_ASSERT( is_pointer, pointer_type,      true );
    STATIC_ASSERT( is_pointer, fun_type,          false );
    STATIC_ASSERT( is_pointer, pfun_type,         true );
    STATIC_ASSERT( is_pointer, fun_ref_type,      false );
    STATIC_ASSERT( is_pointer, enum_type,         false );
    STATIC_ASSERT( is_pointer, enum_class_type,   false );
    STATIC_ASSERT( is_pointer, struct_type,       false );
    STATIC_ASSERT( is_pointer, union_type,        false );
    STATIC_ASSERT( is_pointer, mem_data_ptr_type, false );
    STATIC_ASSERT( is_pointer, mem_fun_ptr_type,  false );
    STATIC_ASSERT( is_pointer, mem_fun_ptr_type2, false );

    STATIC_ASSERT( is_object, arithmetic_type,   true );
    STATIC_ASSERT( is_object, void_type,         false );
    STATIC_ASSERT( is_object, lref_type,         false );
    STATIC_ASSERT( is_object, rref_type,         false );
    STATIC_ASSERT( is_object, array_type,        true );
    STATIC_ASSERT( is_object, array_type2,       true );
    STATIC_ASSERT( is_object, pointer_type,      true );
    STATIC_ASSERT( is_object, fun_type,          false );
    STATIC_ASSERT( is_object, pfun_type,         true );
    STATIC_ASSERT( is_object, fun_ref_type,      false );
    STATIC_ASSERT( is_object, enum_type,         true );
    STATIC_ASSERT( is_object, enum_class_type,   true );
    STATIC_ASSERT( is_object, struct_type,       true );
    STATIC_ASSERT( is_object, union_type,        true );
    STATIC_ASSERT( is_object, mem_data_ptr_type, true );
    STATIC_ASSERT( is_object, mem_fun_ptr_type,  true );
    STATIC_ASSERT( is_object, mem_fun_ptr_type2, true );

    STATIC_ASSERT( is_function, arithmetic_type,   false );
    STATIC_ASSERT( is_function, void_type,         false );
    STATIC_ASSERT( is_function, lref_type,         false );
    STATIC_ASSERT( is_function, rref_type,         false );
    STATIC_ASSERT( is_function, array_type,        false );
    STATIC_ASSERT( is_function, array_type2,       false );
    STATIC_ASSERT( is_function, pointer_type,      false );
    STATIC_ASSERT( is_function, fun_type,          true );
    STATIC_ASSERT( is_function, pfun_type,         false );
    STATIC_ASSERT( is_function, fun_ref_type,      false );
    STATIC_ASSERT( is_function, enum_type,         false );
    STATIC_ASSERT( is_function, enum_class_type,   false );
    STATIC_ASSERT( is_function, struct_type,       false );
    STATIC_ASSERT( is_function, union_type,        false );
    STATIC_ASSERT( is_function, mem_data_ptr_type, false );
    STATIC_ASSERT( is_function, mem_fun_ptr_type,  false );
    STATIC_ASSERT( is_function, mem_fun_ptr_type2, false );

    STATIC_ASSERT( is_unscoped_enum, arithmetic_type,   false );
    STATIC_ASSERT( is_unscoped_enum, void_type,         false );
    STATIC_ASSERT( is_unscoped_enum, lref_type,         false );
    STATIC_ASSERT( is_unscoped_enum, rref_type,         false );
    STATIC_ASSERT( is_unscoped_enum, array_type,        false );
    STATIC_ASSERT( is_unscoped_enum, array_type2,       false );
    STATIC_ASSERT( is_unscoped_enum, pointer_type,      false );
    STATIC_ASSERT( is_unscoped_enum, fun_type,          false );
    STATIC_ASSERT( is_unscoped_enum, pfun_type,         false );
    STATIC_ASSERT( is_unscoped_enum, fun_ref_type,      false );
    STATIC_ASSERT( is_unscoped_enum, enum_type,         true );
    STATIC_ASSERT( is_unscoped_enum, enum_class_type,   !ENUM_CLASS_IS_SCOPED );
    STATIC_ASSERT( is_unscoped_enum, struct_type,       false );
    STATIC_ASSERT( is_unscoped_enum, union_type,        false );
    STATIC_ASSERT( is_unscoped_enum, mem_data_ptr_type, false );
    STATIC_ASSERT( is_unscoped_enum, mem_fun_ptr_type,  false );
    STATIC_ASSERT( is_unscoped_enum, mem_fun_ptr_type2, false );

    STATIC_ASSERT( is_scoped_enum, arithmetic_type,   false );
    STATIC_ASSERT( is_scoped_enum, void_type,         false );
    STATIC_ASSERT( is_scoped_enum, lref_type,         false );
    STATIC_ASSERT( is_scoped_enum, rref_type,         false );
    STATIC_ASSERT( is_scoped_enum, array_type,        false );
    STATIC_ASSERT( is_scoped_enum, array_type2,       false );
    STATIC_ASSERT( is_scoped_enum, pointer_type,      false );
    STATIC_ASSERT( is_scoped_enum, fun_type,          false );
    STATIC_ASSERT( is_scoped_enum, pfun_type,         false );
    STATIC_ASSERT( is_scoped_enum, fun_ref_type,      false );
    STATIC_ASSERT( is_scoped_enum, enum_type,         false );
    STATIC_ASSERT( is_scoped_enum, enum_class_type,   ENUM_CLASS_IS_SCOPED );
    STATIC_ASSERT( is_scoped_enum, struct_type,       false );
    STATIC_ASSERT( is_scoped_enum, union_type,        false );
    STATIC_ASSERT( is_scoped_enum, mem_data_ptr_type, false );
    STATIC_ASSERT( is_scoped_enum, mem_fun_ptr_type,  false );
    STATIC_ASSERT( is_scoped_enum, mem_fun_ptr_type2, false );

    STATIC_ASSERT( is_enum, arithmetic_type,   false );
    STATIC_ASSERT( is_enum, void_type,         false );
    STATIC_ASSERT( is_enum, lref_type,         false );
    STATIC_ASSERT( is_enum, rref_type,         false );
    STATIC_ASSERT( is_enum, array_type,        false );
    STATIC_ASSERT( is_enum, array_type2,       false );
    STATIC_ASSERT( is_enum, pointer_type,      false );
    STATIC_ASSERT( is_enum, fun_type,          false );
    STATIC_ASSERT( is_enum, pfun_type,         false );
    STATIC_ASSERT( is_enum, fun_ref_type,      false );
    STATIC_ASSERT( is_enum, enum_type,         true );
    STATIC_ASSERT( is_enum, enum_class_type,   true );
    STATIC_ASSERT( is_enum, struct_type,       false );
    STATIC_ASSERT( is_enum, union_type,        false );
    STATIC_ASSERT( is_enum, mem_data_ptr_type, false );
    STATIC_ASSERT( is_enum, mem_fun_ptr_type,  false );
    STATIC_ASSERT( is_enum, mem_fun_ptr_type2, false );

    STATIC_ASSERT( is_mem_data_ptr, arithmetic_type,   false );
    STATIC_ASSERT( is_mem_data_ptr, void_type,         false );
    STATIC_ASSERT( is_mem_data_ptr, lref_type,         false );
    STATIC_ASSERT( is_mem_data_ptr, rref_type,         false );
    STATIC_ASSERT( is_mem_data_ptr, array_type,        false );
    STATIC_ASSERT( is_mem_data_ptr, array_type2,       false );
    STATIC_ASSERT( is_mem_data_ptr, pointer_type,      false );
    STATIC_ASSERT( is_mem_data_ptr, fun_type,          false );
    STATIC_ASSERT( is_mem_data_ptr, pfun_type,         false );
    STATIC_ASSERT( is_mem_data_ptr, fun_ref_type,      false );
    STATIC_ASSERT( is_mem_data_ptr, enum_type,         false );
    STATIC_ASSERT( is_mem_data_ptr, enum_class_type,   false );
    STATIC_ASSERT( is_mem_data_ptr, struct_type,       false );
    STATIC_ASSERT( is_mem_data_ptr, union_type,        false );
    STATIC_ASSERT( is_mem_data_ptr, mem_data_ptr_type, true );
    STATIC_ASSERT( is_mem_data_ptr, mem_fun_ptr_type,  false );
    STATIC_ASSERT( is_mem_data_ptr, mem_fun_ptr_type2, false );

    STATIC_ASSERT( is_mem_fun_ptr, arithmetic_type,   false );
    STATIC_ASSERT( is_mem_fun_ptr, void_type,         false );
    STATIC_ASSERT( is_mem_fun_ptr, lref_type,         false );
    STATIC_ASSERT( is_mem_fun_ptr, rref_type,         false );
    STATIC_ASSERT( is_mem_fun_ptr, array_type,        false );
    STATIC_ASSERT( is_mem_fun_ptr, array_type2,       false );
    STATIC_ASSERT( is_mem_fun_ptr, pointer_type,      false );
    STATIC_ASSERT( is_mem_fun_ptr, fun_type,          false );
    STATIC_ASSERT( is_mem_fun_ptr, pfun_type,         false );
    STATIC_ASSERT( is_mem_fun_ptr, fun_ref_type,      false );
    STATIC_ASSERT( is_mem_fun_ptr, enum_type,         false );
    STATIC_ASSERT( is_mem_fun_ptr, enum_class_type,   false );
    STATIC_ASSERT( is_mem_fun_ptr, struct_type,       false );
    STATIC_ASSERT( is_mem_fun_ptr, union_type,        false );
    STATIC_ASSERT( is_mem_fun_ptr, mem_data_ptr_type, false );
    STATIC_ASSERT( is_mem_fun_ptr, mem_fun_ptr_type,  true );
    STATIC_ASSERT( is_mem_fun_ptr, mem_fun_ptr_type2, true );
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2241537</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2241537</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Mon, 13 Aug 2012 22:28:51 GMT</pubDate></item></channel></rss>