[Disclaimer: I know an answer to this question. I thought it might be of some general interest.]
Question: How can we have a type trait that produces the type that results from performing default argument promotions?
Motivation: I would like to be able to use variable arguments portably. For example:
void foo(char const * fmt, ...); // Please pass: * unsigned short
// * bool
// * char32_t
// * unsigned char
When passing arguments to a function call without parameters, i.e. matching the ellipsis, the arguments undergo default argument promotion. So far so good, but those promotions are platform dependent. I can recover the arguments with va_arg(ap, T), but what is T?
Now, for some simple situations this is easy: For example, I can always say:
unsigned short n = va_args(ap, unsigned int);
The default promotion will result in either a signed int or an unsigned int, but according to, say, C11 7.16.1.1/3, va-casting to unsigned int is always fine, since even if the default promotion results in an int, the original value can be represented by both types.
But what type should I cast to when I expect a char32_t? C++11 4.5/2 leaves the resulting type wide open. So I would like a trait that lets me write:
char32_t c = va_args(ap, default_promote<char32_t>::type);
How to do this?
Bonus points for a trait that produces a static assertion when the parameter type must not be passed as a variable argument.