<?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[Rückgabewerte in allgemeine Form wrappen; was macht man wegen void?]]></title><description><![CDATA[<p>Guten Abend,</p>
<p>Vornweg sei gesagt, dass das, was hier zu versuchen ist, ein reines Experiment darstellt. C++ verkommt immer mehr zu einer Mathematik-artigen Sprache, wo man Dinge ausprobieren kann <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="😃"
    /></p>
<p>Angeommen, man möchte Funktionen jeglichen Rückgabetyps in eine allgemeine Form wrappen, so dass alle die gleiche Signatur aufweisen und denselben Wrapper (hier sei mal <code>boost::any</code> gesetzt) zurückgeben. Hierzu gegeben ist folgender Code, wobei man mit Hilfe von <code>invoke</code> und <code>bind</code> einen Funktions-Wrapper erzeugen kann:</p>
<pre><code class="language-cpp">template&lt;typename result_type&gt;
result_type get_default()
{
    return result_type();
}

template&lt;typename result_type&gt;
any invoke(result_type (*fimpl)())
{
    return fimpl();
}
// Verwendung:
any result = invoke(&amp;get_default&lt;int&gt;);
// Später:
result = invoke(&amp;get_default&lt;string&gt;);
</code></pre>
<p>Wie realisiert man jedoch den Sonderfall, wo die Funktion einen <code>void</code> -Rückgabewert hat, also nichts zurück gibt? Die Variante <code>invoke&lt;void&gt;</code> funktioniert nicht, da ja nichts zurückgegeben wird.</p>
<p>Ich habe eine - zugegeben extrem hässliche - Möglichkeit gefunden, keine Sonderbehandlung programmieren zu müssen, indem ich den <code>operator,</code> überladen habe:</p>
<pre><code class="language-cpp">namespace
{

    template&lt;typename result_type&gt;
    any &amp;operator,(any &amp;lvalue,
                   result_type &amp;&amp;rvalue)
    {
        return lvalue = rvalue;
    }

    template&lt;typename result_type&gt;
    any invoke(result_type (*fimpl)())
    {
        any result;
        result = // Hier passiert, was mir nicht ganz geheuer ist:
            any(),
            fimpl();
        return result;
    }

    long get_long()
    {
        return 42;
    }

    void get_void()
    {
        return;
    }

}

int main()
{
    cout &lt;&lt; &quot;\tlong: &quot; &lt;&lt; invoke(&amp;get_long).type().name() &lt;&lt; endl
         &lt;&lt; &quot;\tvoid: &quot; &lt;&lt; invoke(&amp;get_void).type().name() &lt;&lt; endl;
    //
    cin.clear();
    cin.get();
}
</code></pre>
<p>Für den Fall, dass auf der rechten Seite des <code>operator,</code> ein Ausdruck des Typs <code>void</code> steht, findet die Zuweisung normal statt, gefolgt von der unabhängigen Ausführung des Ausdrucks. Ansonsten wird der zweite Ausdruck dem ersten zugewiesen. Gibt es noch einen weiteren Weg, denselben Effekt zu erreichen?</p>
<p>Es existieren so viele Berührungsängste mit <code>void</code> , dass man den generellen Fall fast nicht beschreiben kann <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/topic/286606/rückgabewerte-in-allgemeine-form-wrappen-was-macht-man-wegen-void</link><generator>RSS for Node</generator><lastBuildDate>Thu, 20 Aug 2026 21:31:28 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/286606.rss" rel="self" type="application/rss+xml"/><pubDate>Thu, 12 May 2011 20:22:37 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Rückgabewerte in allgemeine Form wrappen; was macht man wegen void? on Thu, 12 May 2011 20:25:20 GMT]]></title><description><![CDATA[<p>Guten Abend,</p>
<p>Vornweg sei gesagt, dass das, was hier zu versuchen ist, ein reines Experiment darstellt. C++ verkommt immer mehr zu einer Mathematik-artigen Sprache, wo man Dinge ausprobieren kann <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="😃"
    /></p>
<p>Angeommen, man möchte Funktionen jeglichen Rückgabetyps in eine allgemeine Form wrappen, so dass alle die gleiche Signatur aufweisen und denselben Wrapper (hier sei mal <code>boost::any</code> gesetzt) zurückgeben. Hierzu gegeben ist folgender Code, wobei man mit Hilfe von <code>invoke</code> und <code>bind</code> einen Funktions-Wrapper erzeugen kann:</p>
<pre><code class="language-cpp">template&lt;typename result_type&gt;
result_type get_default()
{
    return result_type();
}

template&lt;typename result_type&gt;
any invoke(result_type (*fimpl)())
{
    return fimpl();
}
// Verwendung:
any result = invoke(&amp;get_default&lt;int&gt;);
// Später:
result = invoke(&amp;get_default&lt;string&gt;);
</code></pre>
<p>Wie realisiert man jedoch den Sonderfall, wo die Funktion einen <code>void</code> -Rückgabewert hat, also nichts zurück gibt? Die Variante <code>invoke&lt;void&gt;</code> funktioniert nicht, da ja nichts zurückgegeben wird.</p>
<p>Ich habe eine - zugegeben extrem hässliche - Möglichkeit gefunden, keine Sonderbehandlung programmieren zu müssen, indem ich den <code>operator,</code> überladen habe:</p>
<pre><code class="language-cpp">namespace
{

    template&lt;typename result_type&gt;
    any &amp;operator,(any &amp;lvalue,
                   result_type &amp;&amp;rvalue)
    {
        return lvalue = rvalue;
    }

    template&lt;typename result_type&gt;
    any invoke(result_type (*fimpl)())
    {
        any result;
        result = // Hier passiert, was mir nicht ganz geheuer ist:
            any(),
            fimpl();
        return result;
    }

    long get_long()
    {
        return 42;
    }

    void get_void()
    {
        return;
    }

}

int main()
{
    cout &lt;&lt; &quot;\tlong: &quot; &lt;&lt; invoke(&amp;get_long).type().name() &lt;&lt; endl
         &lt;&lt; &quot;\tvoid: &quot; &lt;&lt; invoke(&amp;get_void).type().name() &lt;&lt; endl;
    //
    cin.clear();
    cin.get();
}
</code></pre>
<p>Für den Fall, dass auf der rechten Seite des <code>operator,</code> ein Ausdruck des Typs <code>void</code> steht, findet die Zuweisung normal statt, gefolgt von der unabhängigen Ausführung des Ausdrucks. Ansonsten wird der zweite Ausdruck dem ersten zugewiesen. Gibt es noch einen weiteren Weg, denselben Effekt zu erreichen?</p>
<p>Es existieren so viele Berührungsängste mit <code>void</code> , dass man den generellen Fall fast nicht beschreiben kann <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/2062495</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2062495</guid><dc:creator><![CDATA[*rant*]]></dc:creator><pubDate>Thu, 12 May 2011 20:25:20 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabewerte in allgemeine Form wrappen; was macht man wegen void? on Thu, 12 May 2011 21:00:26 GMT]]></title><description><![CDATA[<p>Worauf willst du am Ende hinaus? Der Rückgabewert zählt sowieso nicht zur Funktionssignatur.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2062529</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2062529</guid><dc:creator><![CDATA[SeppJ]]></dc:creator><pubDate>Thu, 12 May 2011 21:00:26 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabewerte in allgemeine Form wrappen; was macht man wegen void? on Thu, 12 May 2011 21:16:43 GMT]]></title><description><![CDATA[<p>Zusammengefasst: <code>invoke</code> soll eine beliebige Funktion aufrufen und muss immer ein <code>any</code> zurückgeben. Wenn die aufgerufene Funktion den Rückgabetyp <code>void</code> hat, muss ein leeres <code>any</code> zurückgegeben werden. Wie formuliere ich <code>invoke</code> so, dass es auch mit <code>void</code> klar kommt?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2062535</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2062535</guid><dc:creator><![CDATA[*rant*]]></dc:creator><pubDate>Thu, 12 May 2011 21:16:43 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabewerte in allgemeine Form wrappen; was macht man wegen void? on Fri, 13 May 2011 05:14:19 GMT]]></title><description><![CDATA[<p>Ich habe dafür immer zwei versionen von invoke gemacht.<br />
Eine z.B. invokeWithReturn(..) und eine invokeWithoutReturn(..).</p>
<p>Gefällt mir nicht sonderlich - bin also auch an einer eleganteren Lösung interessiert.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2062569</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2062569</guid><dc:creator><![CDATA[theta]]></dc:creator><pubDate>Fri, 13 May 2011 05:14:19 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabewerte in allgemeine Form wrappen; was macht man wegen void? on Fri, 13 May 2011 05:56:59 GMT]]></title><description><![CDATA[<p><code>invoke&lt;void&gt;</code> spezialisieren?</p>
<pre><code class="language-cpp">template&lt;typename result_type&gt;
any invoke(result_type (*fimpl)())
{
    return fimpl();
}

template&lt;&gt;
any invoke&lt;void&gt;(void (*fimpl)())
{
    fimpl();
    return any();
}
</code></pre>
<p>Oder übersehe ich etwas?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2062576</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2062576</guid><dc:creator><![CDATA[ipsec]]></dc:creator><pubDate>Fri, 13 May 2011 05:56:59 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabewerte in allgemeine Form wrappen; was macht man wegen void? on Fri, 13 May 2011 09:27:10 GMT]]></title><description><![CDATA[<p>Ich denke jeder Compiler schluckt ein</p>
<pre><code class="language-cpp">void wrapper()
{
  return returnsVoid();
}
</code></pre>
<p>MSVC tuts auf jeden Fall. Zumindestens bei templates.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2062677</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2062677</guid><dc:creator><![CDATA[Ethon]]></dc:creator><pubDate>Fri, 13 May 2011 09:27:10 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabewerte in allgemeine Form wrappen; was macht man wegen void? on Fri, 13 May 2011 09:33:28 GMT]]></title><description><![CDATA[<p>ipsec schrieb:</p>
<blockquote>
<p><code>invoke&lt;void&gt;</code> spezialisieren?</p>
<pre><code class="language-cpp">template&lt;typename result_type&gt;
any invoke(result_type (*fimpl)())
{
    return fimpl();
}

template&lt;&gt;
any invoke&lt;void&gt;(void (*fimpl)())
{
    fimpl();
    return any();
}
</code></pre>
<p>Oder übersehe ich etwas?</p>
</blockquote>
<p>Nein, so kann man es lösen. Allerdings wollte ich diese Lösung vermeiden, da es mit der Zeit sehr viele Spezialisierungen brauchen könnte, etwa so:</p>
<pre><code class="language-cpp">template&lt;typename object_type&gt;
any invoke(any obj_r, void (object_type::*fimpl)())
{
    (any_cast&lt;object_type *&gt;(obj_r)-&gt;*fimpl)();
    return any();
}
template&lt;typename object_type&gt;
any invoke(any obj_r, void (object_type::*fimpl)() const)
{
    (any_cast&lt;object_type *&gt;(obj_r)-&gt;*fimpl)();
    return any();
}
template&lt;typename object_type&gt;
any invoke(any obj_r, void (object_type::*fimpl)() volatile)
{
    (any_cast&lt;object_type *&gt;(obj_r)-&gt;*fimpl)();
    return any();
}
</code></pre>
<p>Jetzt stell dir vor, dass man noch weitere Signaturen unterstützen will. Für jede Variante, die noch <code>void</code> zurückgibt, kann man neu überladen.</p>
<p>Ethon schrieb:</p>
<blockquote>
<p>Ich denke jeder Compiler schluckt ein</p>
<pre><code class="language-cpp">void wrapper()
{
  return returnsVoid();
}
</code></pre>
<p>MSVC tuts auf jeden Fall. Zumindestens bei templates.</p>
</blockquote>
<p>Das ist klar, aber es soll ja für alle Fälle any returned werden <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/2062685</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2062685</guid><dc:creator><![CDATA[*rant*]]></dc:creator><pubDate>Fri, 13 May 2011 09:33:28 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabewerte in allgemeine Form wrappen; was macht man wegen void? on Fri, 13 May 2011 09:54:24 GMT]]></title><description><![CDATA[<p>Kannst du dir nicht vielleicht was mit <a href="http://www.boost.org/doc/libs/1_46_1/libs/type_traits/doc/html/boost_typetraits/reference/is_void.html" rel="nofollow">TypeTraits</a> und <a href="http://www.boost.org/doc/libs/1_46_1/libs/utility/enable_if.html" rel="nofollow">enable_if</a> zusammenbasteln?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2062702</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2062702</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Fri, 13 May 2011 09:54:24 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabewerte in allgemeine Form wrappen; was macht man wegen void? on Fri, 13 May 2011 10:14:54 GMT]]></title><description><![CDATA[<p>Da brauchst du schon ein paar mehr Hilfsmittel, du musst ja aber das Rad nicht immer neu erfinden:</p>
<pre><code class="language-cpp">template&lt;class Result, class Func&gt;
struct invoke_wrapper
{
	static any call(Func&amp;&amp; f)
	{
		return f();
	}
}

template&lt;class Func&gt;
struct invoke_wrapper&lt;void&gt;
{
	static any call(Func&amp;&amp; f)
	{
		f();
		return any();
	}
}

template&lt;class Func&gt;
any invoke(Func&amp;&amp; f)
{
	return invoke_wrapper&lt;result_of&lt;Func&gt;::type, Func&gt;::call(f);
}

template&lt;typename result_type, typename object_type&gt;
any invoke(any obj_r, result_type (object_type::*fimpl)())
{
	return invoke(bind(fimpl, any_cast&lt;object_type*&gt;(obj_r)));
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2062713</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2062713</guid><dc:creator><![CDATA[ipsec]]></dc:creator><pubDate>Fri, 13 May 2011 10:14:54 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabewerte in allgemeine Form wrappen; was macht man wegen void? on Fri, 13 May 2011 11:20:25 GMT]]></title><description><![CDATA[<p>Ich würds weiterleiten an ein template, das zwei Parameter hat, nämlich die Funktionssignatur und den Return-Typ:</p>
<pre><code class="language-cpp">template &lt;class F, class Return_t = std::tr1::result_of&lt;F&gt;::type&gt;
struct generate_any
{
  any operator()(F f)
  {
    return f();
  }
};

template &lt;class F, void&gt;
struct generate_any
{
  any operator()(F f)
  {
    f();
    return any();
  }
}

//Anwendung deiner Beispiele:
template&lt;typename result_type&gt;
any invoke(result_type (*fimpl)())
{
  generate_any&lt;result_type(*)() /*, result_type*/&gt; g; 
  return g(fimpl);
}

template&lt;typename object_type, typename return_type&gt;
any invoke(any obj_r, return_type (object_type::*fimpl)())
{
  generate_any&lt;void (object_type::*)() /*, return_type*/&gt; g;
  return g( std::tr1::bind(fimpl, any_cast&lt;object_type*&gt;(obj_r)) );
}
//usw.
</code></pre>
<p>Man könnte mit C++0x jetzt noch weiter gehn:</p>
<pre><code class="language-cpp">template &lt;class R, class... A, class... B&gt;
any invoke(std::function&lt;R(A...)&gt; f, B...Args);
</code></pre>
<p>Wenn man den Aufruf an ein Functor-Template weiterleitet, kann man darin bereits zur Compilezeit alles mögliche anstellen, vor allem die einzelnen Typen in B... überprüfen, wenns any's sind, beim Aufruf von f einen any_cast auf den passenden Typen in A... ausführen usw.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2062739</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2062739</guid><dc:creator><![CDATA[pumuckl]]></dc:creator><pubDate>Fri, 13 May 2011 11:20:25 GMT</pubDate></item></channel></rss>