That is fine but the meaning of your terminology "and no syntax to name the
last mandatory parameter" still eludes me. Are you saying that the
paragraph in the standard should have been phrased differently ?
> Thus it might be
>>> cumbersome to use the standard syntax to implement
>>> int printf(const char *fmt, ...) as a macro that invokes
>>> int fprintf_private(FILE *f, const char *fmt, size_t fmtlen, ...).
>>>
>>>
>> If the ... might have 0 parameters then the macro is:
>>
>> int printf(...)
>>
>
> I'm not sure what the above is supposed to be. You call it a macro, yet
> there's an 'int' rather than a #define at the front, which makes it
> appear to be a declaration.
>
I was responding to the "standard syntax to implement
int printf(const char *fmt, ...) as a macro" etc. I assume this meant
something like:
#define printf(fmt,...)
and the suggestion that it might be cumbersome comes from the fact that a
varying argument function does not need any arguments to be passed to the
function for the ellipsis but that a variadic macro must have at least one
argument passed when it specifies the variadic parameter syntax of '...'.
My solution to that would be to have the variadic function be:
#define printf(...) etc.
where the first variadic argument is the 'fmt' and the optional variadic
arguments would correspond to the ellipsis arguments. The variadic macro
support in Boost PP makes it possible to extract any variadic parameter
from the variadic as well as determine the number of variadic parameters of
the variadic data. So while it might be cumbersome to use the standard
syntax it is not impossible to do so.
The declaration for printf is
>
> int printf(const char * restrict format, ...);
>
> In order for printf() to be defined as macro that calls
> fprintf_private() while allowing it be called with only a format string
> (as is legal), it would have to look something like this:
>
> // Remove any pre-existing #define of printf() by the implementation.
> #undef printf
> #define printf(...) fprintf_private(stdout, \\
> count_va_args(#__VA_ARGS__), __VA_ARGS__)
>
> If it weren't done that way, printf("Hello World!") would violate
> 16.3p4, so fmt cannot be passed as the second argument of
> fprintf_private(), as originally specified by Jakob Bohm. It would have
> to be passed along with the variable part of the argument list.
>
I do not believe your syntax above does work, but then I am not sure what
the syntax of fprintf_private is supposed to be. From your previous post
you specified it as:
int fprintf_private(FILE *f, const char *fmt, size_t fmtlen, ...)
but that suggests that 'fmtlen' is a required argument also. In your
implementation above I assume 'stdout' is the argument for 'FILE * f' but I
don't see an argument for 'fmt'. I am guessing that
'count_va_args(#__VA_ARGS__)' is the argument for 'fmtlen' and that
'fmtlen' is the number of varying arguments from 0 to whatever it is.
Assuming that you are trying to create a 'printf' macro to invoke 'int
fprintf_private(FILE *f, const char *fmt, size_t fmtlen, ...)', where
'stdout' is hardcoded as 'FILE *f' and 'fmtlen' is the number of varying
arguments, the Boost PP syntax would be:
#include <boost/preprocessor/comparison/equal.hpp>
#include <boost/preprocessor/control/iif.hpp>
#include <boost/preprocessor/tuple/enum.hpp>
#include <boost/preprocessor/tuple/po_front.hpp>
#include <boost/preprocessor/variadic/elem.hpp>
#include <boost/preprocessor/variadic/size.hpp>
#include <boost/preprocessor/variadic/to_tuple.hpp>
#define printf(...) \
BOOST_PP_IIF \
( \
BOOST_PP_EQUAL(BOOST_PP_VARIADIC_SIZE,1), \
printf_SINGLE, \
printf_MULTIPLE \
) \
(__VA_ARGS__)
#define printf_SINGLE(...) \
fprintf_private \
( \
stdout, \
BOOST_PP_VARIADIC_ELEM(0,__VA_ARGS__), \
0 \
)
#define printf_MULTIPLE \
fprintf_private \
( \
stdout, \
BOOST_PP_VARIADIC_ELEM(0,__VA_ARGS__), \
BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), \
BOOST_PP_TUPLE_ENUM \
( \
BOOST_PP_TUPLE_POP_FRONT \
( \
BOOST_PP_VARIADIC_TO_TUPLE(__VA_ARGS__) \
) \
) \
)
I agree this is not as simple as allowing an end-user to not pass an
argument for variadic data as gcc does, but it is certainly doable via
Boost PP. Maybe "cumbersome" is an apt word unless one knows Boost PP macro
programming <g>.