2013/5/16 Daryle Walker <
dar...@gmail.com>:
> This is based on a recent query I made on Stack Overflow. I tried test code
> on a compiling website running GCC 4.8.
>
> 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... );
> //...
> }
>
> The code only worked when sizeof...(a) exactly one, neither more nor less.
> Worse, when a was empty, I could use x as the last-normal parameter instead!
There are several problems with that code:
1) va_start expects exactly two arguments.
2) The second argument shall not be a reference type, and if, the
behaviour is undefined.
3) I don't understand how you expect the parameter pack and the
ellipses parameter to cooperate.
4) Your example is so incomplete that I don't understand in which call
context you believe it should work.
The first two arguments are requirements imposed by a macro that stems
from the C Standard Library.
> What I expect to happen:
> I can use "a" as the last-normal parameter in va_start, no matter if a
> represents one, more, or zero expansion arguments.
Why do you expect that? It might be technical feasible by changing the
macro specification of C++ to expect a variadic macro, but I'm a
little bit surprised, why this support, that this use-case is so
important (At the moment I don't understand this use-case), that the
effort to change the specification of that macro should be changed. It
is really not so hard to provide a function template definition, that
returns always the last element of a parameter pack, so given that
definition you could write
va_start( args2, last(a...) );
instead. Even if you solve the problem, when do you expect that the
ellipses parameter could be non-empty? Do you always want to provide
the pack types of my_func as explicit template arguments?
> I shouldn't be able to
> use x when a is empty.
Why not? This can also me reasonable (but I don't see a way how to
provide an explicit empty pack, how would you do that?). Assuming you
solved the technical problems: If you don't like that, you can static
assert on the pack length, so it won't be able.
> (And what happens if there isn't an extra prior
> argument like x?)
A reasonable assumption for me would be that parameter x is the last
one. What other choices do you envision?
> I'm flexible on whether we can use "a", or we must still use "a...". For
> the latter, maybe va_start needs to be a variadic macro? Hmm, how should it
> work if a is empty and there's no prior arguments?
I recommend to construct your own varidic function template that
solves this parameter choice for you. For proper integration of x (or
not), you could call it as so:
va_start( args2, last(x, a...) );
so it will never be empty. Implement last() to the most preferred way
you like (I don't see any reasons that it couldn't).
> Possible solution:
> Change Section 18.10 [support.runtime], paragraph 3, footnote 227 to:
> Note that va_start is required to work as specified even if unary operator&
> is overloaded for the type of parmN, or parmN is a pack expansion, or both.
Why is now unary operator& important for you? Again, you could solve
this via your own last function template that internally calls
std::addressof for the returned argument.
From what I'm seeing sofar I really cannot deduce a real need for a
standardized solution of the use-case you mention. Especially because
I think that the combination of variadic parameters with the ellipses
parameter is also not natural to use, plus the IMO missing support for
explicit empty pack expansions.
- Daniel