Please help me understand this C++ parameter declaration with an argument
Asked Answered
B

1

6

I use the ROOT C++ libraries (root.cern.ch) daily and was browsing the source when I came across this function declaration:

TString TString::Format(const char *va_(fmt), ...)
{
    //etc.

It can be found here.

I don't understand how a const char * can have an argument or a parenthesis in its name. The expression va_(fmt) is later used as a simple const char * even though it looks like a function call or a constructor. At first I thought it had something to do with the variable argument list, which was also new to me, but reading documentation on stdarg.h didn't help with this question at all.

It is very hard to google for help since I'm not really sure what to call this. A declaration with an argument? That doesn't give any good results.

I used to think I knew C++, but what is going on here? All help will be appreciated.

Broadbent answered 20/3, 2012 at 14:30 Comment(1)
My guess is that va_ is simply a macro. Probably one that does nothing but expand to its parameter.Anapest
C
11

It's a macro - in Varargs.h:

#if ...
#  define va_(arg) __builtin_va_alist
#else
#  define va_(arg) arg
#endif
Coplanar answered 20/3, 2012 at 14:33 Comment(6)
We tell C programmers that #define just obfuscates, but do they believe us? No... ^_-Nagy
Another example of why macros are bad. If fmt were a type then the syntax would be a valid declaration of a function taking, as an argument named va_, a pointer to a function returning char const *.Evapotranspiration
How does this even make any difference in the function in question, compared to just naming the parameter va_fmt?Chelsea
@Chelsea Joe leaves out the clause on the #if. It's probably something like #if SOME_FANCY_OPTIMIZED_STDARG_COMPILER_OPTION_ENABLED. What this code does is give you TString TString::Format(const char *__builtin_va_alist, ...) if the fancy compiler option is enabled, or TString TString::Format(const char *fmt, ...) if not. There's no va_fmt anywhere.Nagy
@MikeDeSimone: yeah I know. The thing is, inside the function the parameter is only ever called through the macro, there's no plain __builtin_va_list or fmt. So regardless of what the macro expands to, that name will turn up, shadow any variable with the same name outside the function, and lead to exactly the same behaviour regardless what the name is. That's what I think, but obviously I'm missing something.Chelsea
What you're missing is that the compiler treats __builtin_va_list specially, and not as a straight forward parameter name. Generally, anything starting with a double underscore is compiler secret sauce.Nagy

© 2022 - 2024 — McMap. All rights reserved.