Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I've tried this code out on a compiling web site (Coliru), with GCC 4.8, and the results look bleak. I don't know if it's GCC in particular, or if all the other compilers out there do something similar. So can people with other compilers (Clang, Visual C++, Intel, etc.) try this out?</p> <pre><code>#include &lt;cstdarg&gt; #include &lt;iostream&gt; #include &lt;ostream&gt; #include &lt;utility&gt; template &lt; typename ...Args &gt; int super_vaprintf( long, std::va_list &amp;, Args &amp;&amp;... ) { return 17; } template &lt; typename ...Args &gt; int super_printf( long x, Args &amp;&amp;...a, ... ) { std::va_list args2; int result; va_start( args2, a ); // (A) try { result = super_vaprintf( x, args2, std::forward&lt;Args&gt;(a)... ); } catch ( ... ) { va_end( args2 ); throw; } va_end( args2 ); return result; } int main() { std::cout &lt;&lt; super_printf&lt;int, int&gt;( 0L, 1, 2, 3, 4, 5 ) &lt;&lt; std::endl; // (B) return 0; } </code></pre> <p>The call to <code>super_printf</code> on line (B) explicitly sets the C++ varargs to two <code>int</code> entries. This will make the function use arguments <code>1</code> and <code>2</code> as C++ varargs and the latter three as C varargs.</p> <p>On line (A), the compiler insists that the code with <code>a</code> in it have a "<code>...</code>" somewhere. So I change it to:</p> <pre><code>va_start( args2, a... ); // (A) </code></pre> <p>I get another error about having the wrong number of arguments. It makes sense since <code>a</code> expands to two arguments. If I change line (B) to one C++ vararg:</p> <pre><code>std::cout &lt;&lt; super_printf&lt;int&gt;( 0L, 1, 2, 3, 4, 5 ) &lt;&lt; std::endl; // (B) </code></pre> <p>it works just fine. If I remove the C++ varargs entirely:</p> <pre><code>std::cout &lt;&lt; super_printf&lt;&gt;( 0L, 1, 2, 3, 4, 5 ) &lt;&lt; std::endl; // (B) </code></pre> <p>we get the wrong-number-or-arguments error again, because <code>a</code> has length of zero). If we do this when <code>a</code> is empty:</p> <pre><code>va_start( args2, x /*a...*/ ); // (A) </code></pre> <p>the code works again, although there is a warning about <code>x</code> not being the last named parameter.</p> <p>We can approach the example in another way. Let's reset to:</p> <pre><code>va_start( args2, a... ); // (A) //... std::cout &lt;&lt; super_printf( 0L, 1, 2, 3, 4, 5 ) &lt;&lt; std::endl; // (B) </code></pre> <p>where all the arguments after the first are grouped as C++ varargs. We get the same too-many-arguments error in <code>va_start</code>, of course. I progressively comment out trailing arguments. It works when there are exactly two arguments left (which makes <code>a</code> have exactly one argument).</p> <p>There is also an error when there's only one argument left, but the error message changes to explicitly say "too few" arguments instead of "wrong amount." Like before, I switched out "<code>a...</code>" for "<code>x</code>" in line (A), and the code was accepted, but there was no warning. So it seems that when I explicitly include "<code>&lt;Whatever&gt;</code>" for <code>super_printf</code> in line (B) I get a different parser error path than when I don't include them, although both paths go to the same conclusion.</p> <p>Time to tell the committee that they overlooked something....</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload