<?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[[C++0x&#x2F;SFINAE] Feststellen, ob eine bestimmte Member-Funktion existiert?]]></title><description><![CDATA[<p>Guten Abend</p>
<p>Aus aktuellem Anlass in einem Projekt (und natürlich auch aus Interesse an den nahezu experimentalen Eigenheiten von C++) wollte ich ein <em>portables</em> Template programmieren, welches feststellt, ob der angegebene Typ <code>T</code> eine bestimmte Member-Funktion <code>T::invoke</code> in der Form <code>void (T::*)() const</code> bereitstellt. Hierzu habe ich unter dem Stichwort <em>SFINAE</em> (engl. &quot;<em>Substitution Failure Is Not An Error</em>&quot;) einige Beispiele gefunden, welche allerdings bei mir prompt nicht kompilierbar waren. Also habe ich die Sache selbst in die Hand genommen und die folgenden Templates geschrieben:</p>
<pre><code class="language-cpp">template&lt;typename query_target_type,
         void (query_target_type::*)() const&gt;
struct sfinae_entity;

template&lt;typename query_target_type&gt;
true_type sfinae_invoke(sfinae_entity&lt;query_target_type,
                                      &amp;query_target_type::invoke&gt; *);
template&lt;typename&gt;
false_type sfinae_invoke(...);

template&lt;typename query_target_type&gt;
struct has_invoke_method
{
    typedef decltype(sfinae_invoke&lt;query_target_type&gt;(0)) type;
};
</code></pre>
<p>Obiger Code macht sich den Umstand zu Nutze, dass C++-Compiler bei der Überladung von Funktionen eigentlich fehlerhafte Template-Anwendungen komplett ignorieren, wenn eine andere Variante bevorzugt werden kann. Wenn also das Template <code>sfinae_entity</code> als Parameter in <code>sfinae_invoke</code> keinen Sinn ergibt, wird die Überladung verworfen und die allgemeine Variante gewählt.</p>
<p>Mit diesen Templates habe ich dann folgendes Test-Programm geschrieben und sowohl mit GCC 4.4.5, als auch mit Visual C++ 2010 zum Laufen gebracht, wobei das Resultat wie gewünscht und erwartet mit beiden Compilern dasselbe ist:</p>
<pre><code class="language-cpp">struct foo
{
    void invoke() const
    {
        cout &lt;&lt; &quot;TEST&quot; &lt;&lt; endl;
    }
};

struct bar
{
};

int main()
{
    // Gibt 1 und 0 aus.
    cout &lt;&lt; has_invoke_method&lt;foo&gt;::type::value &lt;&lt; endl
         &lt;&lt; has_invoke_method&lt;bar&gt;::type::value &lt;&lt; endl;
}
</code></pre>
<p>Wie portabel ist diese Art der Programmierung wirklich? Kann man sich darauf verlassen, dass sowas mit allen konformen Compilern laufen wird? Ich frage, weil die alten Beispiele nicht laufen wollten.</p>
<p>Mit freundlichen Grüssen</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/287079/c-0x-sfinae-feststellen-ob-eine-bestimmte-member-funktion-existiert</link><generator>RSS for Node</generator><lastBuildDate>Thu, 20 Aug 2026 14:40:43 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/287079.rss" rel="self" type="application/rss+xml"/><pubDate>Sat, 21 May 2011 21:40:30 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to [C++0x&#x2F;SFINAE] Feststellen, ob eine bestimmte Member-Funktion existiert? on Sat, 21 May 2011 21:45:39 GMT]]></title><description><![CDATA[<p>Guten Abend</p>
<p>Aus aktuellem Anlass in einem Projekt (und natürlich auch aus Interesse an den nahezu experimentalen Eigenheiten von C++) wollte ich ein <em>portables</em> Template programmieren, welches feststellt, ob der angegebene Typ <code>T</code> eine bestimmte Member-Funktion <code>T::invoke</code> in der Form <code>void (T::*)() const</code> bereitstellt. Hierzu habe ich unter dem Stichwort <em>SFINAE</em> (engl. &quot;<em>Substitution Failure Is Not An Error</em>&quot;) einige Beispiele gefunden, welche allerdings bei mir prompt nicht kompilierbar waren. Also habe ich die Sache selbst in die Hand genommen und die folgenden Templates geschrieben:</p>
<pre><code class="language-cpp">template&lt;typename query_target_type,
         void (query_target_type::*)() const&gt;
struct sfinae_entity;

template&lt;typename query_target_type&gt;
true_type sfinae_invoke(sfinae_entity&lt;query_target_type,
                                      &amp;query_target_type::invoke&gt; *);
template&lt;typename&gt;
false_type sfinae_invoke(...);

template&lt;typename query_target_type&gt;
struct has_invoke_method
{
    typedef decltype(sfinae_invoke&lt;query_target_type&gt;(0)) type;
};
</code></pre>
<p>Obiger Code macht sich den Umstand zu Nutze, dass C++-Compiler bei der Überladung von Funktionen eigentlich fehlerhafte Template-Anwendungen komplett ignorieren, wenn eine andere Variante bevorzugt werden kann. Wenn also das Template <code>sfinae_entity</code> als Parameter in <code>sfinae_invoke</code> keinen Sinn ergibt, wird die Überladung verworfen und die allgemeine Variante gewählt.</p>
<p>Mit diesen Templates habe ich dann folgendes Test-Programm geschrieben und sowohl mit GCC 4.4.5, als auch mit Visual C++ 2010 zum Laufen gebracht, wobei das Resultat wie gewünscht und erwartet mit beiden Compilern dasselbe ist:</p>
<pre><code class="language-cpp">struct foo
{
    void invoke() const
    {
        cout &lt;&lt; &quot;TEST&quot; &lt;&lt; endl;
    }
};

struct bar
{
};

int main()
{
    // Gibt 1 und 0 aus.
    cout &lt;&lt; has_invoke_method&lt;foo&gt;::type::value &lt;&lt; endl
         &lt;&lt; has_invoke_method&lt;bar&gt;::type::value &lt;&lt; endl;
}
</code></pre>
<p>Wie portabel ist diese Art der Programmierung wirklich? Kann man sich darauf verlassen, dass sowas mit allen konformen Compilern laufen wird? Ich frage, weil die alten Beispiele nicht laufen wollten.</p>
<p>Mit freundlichen Grüssen</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2066975</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2066975</guid><dc:creator><![CDATA[*rant*]]></dc:creator><pubDate>Sat, 21 May 2011 21:45:39 GMT</pubDate></item><item><title><![CDATA[Reply to [C++0x&#x2F;SFINAE] Feststellen, ob eine bestimmte Member-Funktion existiert? on Sat, 21 May 2011 22:38:59 GMT]]></title><description><![CDATA[<p>Falls du diesen Artikel noch nicht gefunden hast:</p>
<p><a href="http://www.martinecker.com/wiki/index.php?title=Detecting_the_Existence_of_Member_Functions_at_Compile-Time" rel="nofollow">http://www.martinecker.com/wiki/index.php?title=Detecting_the_Existence_of_Member_Functions_at_Compile-Time</a></p>
<p>Mehr hab' ich auf die Schnelle nicht anzubieten.<br />
Was Konformität angeht: mit einem konformen Compiler wirst du im Moment dein Beispiel gar nicht compilieren können, da decltype ein C++0x Feature ist, und C++0x ist noch nicht Standard <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2066984</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2066984</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Sat, 21 May 2011 22:38:59 GMT</pubDate></item><item><title><![CDATA[Reply to [C++0x&#x2F;SFINAE] Feststellen, ob eine bestimmte Member-Funktion existiert? on Sat, 21 May 2011 23:41:47 GMT]]></title><description><![CDATA[<p>Ich konnte auch einen Artikel ausgraben:</p>
<p><a href="http://www.codeproject.com/KB/architecture/Detector.aspx" rel="nofollow">http://www.codeproject.com/KB/architecture/Detector.aspx</a></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2067009</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2067009</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Sat, 21 May 2011 23:41:47 GMT</pubDate></item><item><title><![CDATA[Reply to [C++0x&#x2F;SFINAE] Feststellen, ob eine bestimmte Member-Funktion existiert? on Sun, 22 May 2011 10:26:42 GMT]]></title><description><![CDATA[<p>Danke für die beiden Artikel. Der erste von hustbaer scheint ja erstaunlich nahe an meinem Code zu sein, abgesehen von der Verwendung von <code>decltype</code> , was meiner Meinung nach ein wenig eleganter ist (aber natürlich noch nicht konform; überhaupt weiss ich nicht, ob ich <code>decltype</code> so einsetzen darf...) als der weithin bekannte <code>sizeof</code> -Hack. Beim CodeProject-Artikel gibts noch ein schönes Select-Template, was ich in dieser Form gebrauchen könnte, aber mal schauen, ob TR1 nicht bereits sowas anbietet. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f44d.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--thumbs_up"
      title=":+1:"
      alt="👍"
    /></p>
<p>hustbaer schrieb:</p>
<blockquote>
<p>Was Konformität angeht: mit einem konformen Compiler wirst du im Moment dein Beispiel gar nicht compilieren können, da decltype ein C++0x Feature ist, und C++0x ist noch nicht Standard <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
</blockquote>
<p>Dann wird es Zeit, dass ich denen mal Feuer unter dem Hintern mache, weil mein Code hier bereits an diversen Stellen Dinge wie <code>auto</code> , <code>decltype</code> und Lambda-Ausdrücke verwendet. Im Prinzip hast du natürlich Recht, dass ich mit der Konformität ein wenig früh dran bin. Ich versuche C++0x zu programmieren, was schwierig ist, wenn der Standard noch nicht verabschiedet ist <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f60b.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_savoring_food"
      title=":yum:"
      alt="😋"
    /> <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2067067</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2067067</guid><dc:creator><![CDATA[*rant*]]></dc:creator><pubDate>Sun, 22 May 2011 10:26:42 GMT</pubDate></item></channel></rss>