<?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[unpack von variadic Parameter für void-Funktionsaufruf(e)]]></title><description><![CDATA[<p>Hallo zusammen,</p>
<p>vor einiger Zeit, hat Camper hier ein variadic-Template-Hilfs-Konstrukt gepostet,<br />
das einem ein variadic-Zähler-Parameter zur Verfügung stellt. Generell find ich das Konstrukt echt super, aber jetzt würde ich gerne pro Wert im Vektor eine void-Funktion aufrufen.</p>
<pre><code class="language-cpp">#include &lt;tuple&gt;
#include &lt;iostream&gt;

template &lt;unsigned int... T&gt; struct indexes {}; 
template &lt;typename&gt; struct index_add; 
template &lt;unsigned int... i&gt; struct index_add&lt;indexes&lt;i...&gt; &gt; { typedef indexes&lt;0, ( i + 1 )...&gt; type; }; 
template &lt;unsigned int N&gt; struct make_indexes { typedef typename index_add&lt;typename make_indexes&lt;N-1&gt;::type&gt;::type type; }; 
template &lt;&gt; struct make_indexes&lt;0&gt; { typedef indexes&lt;&gt; type; };

template&lt;typename... T&gt;
void dummy(const T&amp;...t){}

template&lt;typename T&gt;
int print(const T&amp; t){
	std::cout &lt;&lt; t &lt;&lt; std::endl;
	return 0;
}

template&lt;unsigned int... I, typename... T&gt;
void print_all(indexes&lt;I...&gt;, const std::tuple&lt;T...&gt;&amp; tuple){
	dummy(print(std::get&lt;I&gt;(tuple))...);
	// print(std::get&lt;I&gt;(tuple));...
}

int main(){
	std::tuple&lt;int, double, char&gt; tuple(1, 2.0, 'c');
	print_all(make_indexes&lt;3&gt;::type(), tuple);

}
</code></pre>
<p>Solange man in eine andere Funktion oder Konstruktor entpacken kann, ist alles super. Bei einer non-void-Funktion kann man (theoretisch) auch einfach eine Dummy-Funktion schreiben, die eigentlich gar nichts macht...<br />
Aber bei einer void-Funktion sehe ich keine Möglichkeit. Geht es nicht, oder verwende ich eine falsche unpack-Syntax?</p>
<p>Also generell kann ich es natürlich so machen:</p>
<pre><code class="language-cpp">#include &lt;tuple&gt;
#include &lt;iostream&gt;

template &lt;unsigned int... T&gt; struct indexes {}; 
template &lt;typename&gt; struct index_add; 
template &lt;unsigned int... i&gt; struct index_add&lt;indexes&lt;i...&gt; &gt; { typedef indexes&lt;0, ( i + 1 )...&gt; type; }; 
template &lt;unsigned int N&gt; struct make_indexes { typedef typename index_add&lt;typename make_indexes&lt;N-1&gt;::type&gt;::type type; }; 
template &lt;&gt; struct make_indexes&lt;0&gt; { typedef indexes&lt;&gt; type; };

void print(){
}

template&lt;typename TH, typename... T&gt;
void print(const TH&amp; h, const T&amp;... t){
	std::cout &lt;&lt; h &lt;&lt; std::endl;
	print(t...);
}

template&lt;unsigned int... I, typename... T&gt;
void print_all(indexes&lt;I...&gt;, const std::tuple&lt;T...&gt;&amp; tuple){
	print(std::get&lt;I&gt;(tuple)...);
}

int main(){
	std::tuple&lt;int, double, char&gt; tuple(1, 2.0, 'c');
	print_all(make_indexes&lt;3&gt;::type(), tuple);

}
</code></pre>
<p>Gibt es aber nicht einen einfacheren Funktionsaufruf wie im ersten Beispiel angedeutet? Gehe ich richtig in der Annahme, dass die Reihenfolge der print-Aufrufe im 1. Beispiel nicht definiert ist?</p>
<p>Gruß,<br />
XSpille</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/293265/unpack-von-variadic-parameter-für-void-funktionsaufruf-e</link><generator>RSS for Node</generator><lastBuildDate>Sun, 16 Aug 2026 10:44:13 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/293265.rss" rel="self" type="application/rss+xml"/><pubDate>Wed, 28 Sep 2011 22:42:15 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to unpack von variadic Parameter für void-Funktionsaufruf(e) on Wed, 28 Sep 2011 22:42:15 GMT]]></title><description><![CDATA[<p>Hallo zusammen,</p>
<p>vor einiger Zeit, hat Camper hier ein variadic-Template-Hilfs-Konstrukt gepostet,<br />
das einem ein variadic-Zähler-Parameter zur Verfügung stellt. Generell find ich das Konstrukt echt super, aber jetzt würde ich gerne pro Wert im Vektor eine void-Funktion aufrufen.</p>
<pre><code class="language-cpp">#include &lt;tuple&gt;
#include &lt;iostream&gt;

template &lt;unsigned int... T&gt; struct indexes {}; 
template &lt;typename&gt; struct index_add; 
template &lt;unsigned int... i&gt; struct index_add&lt;indexes&lt;i...&gt; &gt; { typedef indexes&lt;0, ( i + 1 )...&gt; type; }; 
template &lt;unsigned int N&gt; struct make_indexes { typedef typename index_add&lt;typename make_indexes&lt;N-1&gt;::type&gt;::type type; }; 
template &lt;&gt; struct make_indexes&lt;0&gt; { typedef indexes&lt;&gt; type; };

template&lt;typename... T&gt;
void dummy(const T&amp;...t){}

template&lt;typename T&gt;
int print(const T&amp; t){
	std::cout &lt;&lt; t &lt;&lt; std::endl;
	return 0;
}

template&lt;unsigned int... I, typename... T&gt;
void print_all(indexes&lt;I...&gt;, const std::tuple&lt;T...&gt;&amp; tuple){
	dummy(print(std::get&lt;I&gt;(tuple))...);
	// print(std::get&lt;I&gt;(tuple));...
}

int main(){
	std::tuple&lt;int, double, char&gt; tuple(1, 2.0, 'c');
	print_all(make_indexes&lt;3&gt;::type(), tuple);

}
</code></pre>
<p>Solange man in eine andere Funktion oder Konstruktor entpacken kann, ist alles super. Bei einer non-void-Funktion kann man (theoretisch) auch einfach eine Dummy-Funktion schreiben, die eigentlich gar nichts macht...<br />
Aber bei einer void-Funktion sehe ich keine Möglichkeit. Geht es nicht, oder verwende ich eine falsche unpack-Syntax?</p>
<p>Also generell kann ich es natürlich so machen:</p>
<pre><code class="language-cpp">#include &lt;tuple&gt;
#include &lt;iostream&gt;

template &lt;unsigned int... T&gt; struct indexes {}; 
template &lt;typename&gt; struct index_add; 
template &lt;unsigned int... i&gt; struct index_add&lt;indexes&lt;i...&gt; &gt; { typedef indexes&lt;0, ( i + 1 )...&gt; type; }; 
template &lt;unsigned int N&gt; struct make_indexes { typedef typename index_add&lt;typename make_indexes&lt;N-1&gt;::type&gt;::type type; }; 
template &lt;&gt; struct make_indexes&lt;0&gt; { typedef indexes&lt;&gt; type; };

void print(){
}

template&lt;typename TH, typename... T&gt;
void print(const TH&amp; h, const T&amp;... t){
	std::cout &lt;&lt; h &lt;&lt; std::endl;
	print(t...);
}

template&lt;unsigned int... I, typename... T&gt;
void print_all(indexes&lt;I...&gt;, const std::tuple&lt;T...&gt;&amp; tuple){
	print(std::get&lt;I&gt;(tuple)...);
}

int main(){
	std::tuple&lt;int, double, char&gt; tuple(1, 2.0, 'c');
	print_all(make_indexes&lt;3&gt;::type(), tuple);

}
</code></pre>
<p>Gibt es aber nicht einen einfacheren Funktionsaufruf wie im ersten Beispiel angedeutet? Gehe ich richtig in der Annahme, dass die Reihenfolge der print-Aufrufe im 1. Beispiel nicht definiert ist?</p>
<p>Gruß,<br />
XSpille</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2124921</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2124921</guid><dc:creator><![CDATA[XSpille]]></dc:creator><pubDate>Wed, 28 Sep 2011 22:42:15 GMT</pubDate></item><item><title><![CDATA[Reply to unpack von variadic Parameter für void-Funktionsaufruf(e) on Thu, 29 Sep 2011 01:49:26 GMT]]></title><description><![CDATA[<p>Die Reihenfolge ist unspezifiziert für Funktionsaufrufe, eine Aggregat-Initialisierung bietet sich deshalb an. Mit variablen Funktionstypen kommt man durch kreative Nutzung des Komma-Operators zurecht. z.B.</p>
<pre><code class="language-cpp">template&lt;unsigned int... I, typename... T&gt;
void print_all(indexes&lt;I...&gt;, const std::tuple&lt;T...&gt;&amp; tuple){
    bool dummy[] = { (print(std::get&lt;I&gt;(tuple)),true)... };
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2124933</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2124933</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Thu, 29 Sep 2011 01:49:26 GMT</pubDate></item><item><title><![CDATA[Reply to unpack von variadic Parameter für void-Funktionsaufruf(e) on Thu, 29 Sep 2011 07:32:51 GMT]]></title><description><![CDATA[<p>camper schrieb:</p>
<blockquote>
<p>Die Reihenfolge ist unspezifiziert für Funktionsaufrufe, eine Aggregat-Initialisierung bietet sich deshalb an. Mit variablen Funktionstypen kommt man durch kreative Nutzung des Komma-Operators zurecht. z.B.</p>
<pre><code class="language-cpp">template&lt;unsigned int... I, typename... T&gt;
void print_all(indexes&lt;I...&gt;, const std::tuple&lt;T...&gt;&amp; tuple){
    bool dummy[] = { (print(std::get&lt;I&gt;(tuple)),true)... };
}
</code></pre>
</blockquote>
<p>Danke dir! <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>Da wäre ich nie draufgekommen...</p>
<p>Dein &quot;deshalb&quot; verstehe ich allerdings nicht. Ist bei deiner Lösung die Reihenfolge spezifiziert? Also intuitiv würde ich sagen &quot;nein&quot;, obwohl es bei meinem Compiler die 'richtige' Reihenfolge ist...</p>
<p>Gruß,<br />
XSpille</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2124955</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2124955</guid><dc:creator><![CDATA[XSpille]]></dc:creator><pubDate>Thu, 29 Sep 2011 07:32:51 GMT</pubDate></item><item><title><![CDATA[Reply to unpack von variadic Parameter für void-Funktionsaufruf(e) on Thu, 29 Sep 2011 11:21:01 GMT]]></title><description><![CDATA[<p>C++11 schrieb:</p>
<blockquote>
<p>8.5.4/4<br />
Within the initializer-list of a braced-init-list, the initializer-clauses, including any that result from pack expansions (14.5.3), are evaluated in the order in which they appear. That is, every value computation and side effect associated with a given initializer-clause is sequenced before every value computation and side effect associated with any initializer-clause that follows it in the comma-separated list of the initializer-list. [ Note: This evaluation ordering holds regardless of the semantics of the initialization; for example, it applies when the elements of the initializer-list are interpreted as arguments of a constructor call, even though ordinarily there are no sequencing constraints on the arguments of a call. —end note ]</p>
</blockquote>
<p>Diese Regel findet sich auch in C++03: die einzelnen Elemente werden in der Reihenfolge ihres Auftretens initialisiert, und zwischen den einzelnen Initialisierern in der Initialisierungsliste befindet sich ein <em>sequence point</em>.<br />
Das ist im Prinzip ganz analog zu Klassenmembern, die im Konstruktor in der Initialisierungsliste initialisiert werden. Es ist zum Beispiel möglich, auf bereits initialisierte Member zuzugreifen.<br />
Sinnfreies Beispiel</p>
<pre><code class="language-cpp">template &lt;int... i&gt; void foo(indexes&lt;i...&gt;)
{
    int fib[] = { 0, 1, (fib[i]+fib[i+1])... };
};
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2125029</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2125029</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Thu, 29 Sep 2011 11:21:01 GMT</pubDate></item><item><title><![CDATA[Reply to unpack von variadic Parameter für void-Funktionsaufruf(e) on Thu, 29 Sep 2011 11:42:23 GMT]]></title><description><![CDATA[<p>DANKE dir! <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>
]]></description><link>https://www.c-plusplus.net/forum/post/2125044</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2125044</guid><dc:creator><![CDATA[XSpille]]></dc:creator><pubDate>Thu, 29 Sep 2011 11:42:23 GMT</pubDate></item></channel></rss>