Re: Yikes! We forgot to encode an iteraction between C++ and C
varargs. (va_start doesn't work with pack expansions.)
On 2013-05-16 15:03, Daryle Walker wrote:
This is based on a recent Stack Overflow post at:
<http://stackoverflow.com/q/16563797/1010226>. As a commenter to my
query indirectly mentioned, we can do this:
[..]
channel C++ varargs into C varargs. But how do we go the other way?
How do we use the va_* stuff for C varargs when the next-to-last
argument is a C++ vararg? My limited testing concludes that it DOES
NOT work.
template < typename ...Args >
int my_func2( short x, std::va_list &aa, Args &&...a );
template < typename ...Args >
int my_func( short x, Args &&...a, ... )
{
std::va_list args2;
va_start( args2, a... );
//...
}
Yes, this cannot work. The code in addition invokes undefined
behaviour for a non.empty pack expansion, because you are using a
parameter of reference type before the ellipses parameter.
I used GCC 4.8 from a compiling website. I initially hoped that I
didn't need to use the "..." after the "a," but I had to. The pack
expansion reacted badly with the "va_start" macro. The code worked
correctly when "sizeof...(a)" was exactly one. It gave errors when
"a" was longer than one AND when it was zero-length. Also, when "a"
was zero-length, I could plug in "x" instead of "a..." and it
worked.
What I expect to happen:
1. I can use "a" as the second parameter of "va_start" without the
"...". If that is not possible (since that usage is currently
illegal everywhere), then "va_start" has to work when "a..." is
given. I don't know how all this works, but maybe the C++ version
of "va_start" needs to be a variadic macro?
2. I cannot use "x" instead when "a..." is empty, since the two
cases can't co-exist because it has to be hard-coded. (Can the
planned "static_if" do it?) In the worse case scenario, the
compiler will secretly switch in "x" for "a..." if it detects that
"a..." is empty; the programmer doesn't have to type in anything
different.
A fix:
Change the footnote (currently #227 in the C++11 standard) for
Section 18.10 [support.runtime], paragraph 3 to:
227) Note that va_start is required to work as speci???ed even if
unary operator& is overloaded for the type of parmN, or parmN is a
pack expansion, or both.
Instead of requiring that the library solves it for you, why not
changing your signature to
template < typename ...Args, typename Last >
int my_func(short x, Args&&...a, Last last, ...)
{
std::va_list args2;
va_start(args2, last);
//...
}
It ensures that you have isolated the last parameter and that it's not
of reference type.
HTH & Greetings from Bremen,
Daniel Kr??gler
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]