Implementing variable length parameter - variadic funetion
-
I screwed-up and started posting code problem in "quick answers' and I am sorry for that. So I cut and paste it here to continue and hopefully resolve the issue
Not much of an improvement - more questions.
I am using the tutorial example and it is complaining about
missing "num" .
I am passing QString as variable number of parametersCopy Code
QString parameter = " TEST message ";
ProcessMessage_Variadic(1, " TEST message ");So what is the problem - the macro
Expand ▼ Copy Codeva_arg
?
declaration
void ProcessMessage_Variadic(int num,...);usage
ProcessMessage_Variadic(1, " TEST message ");definition
void RemoteSelector::ProcessMessage_Variadic (int num,...)
{ui->textEdit->append( "RemoteSelector::ProcessMessage\_Variadic"); QString s = "DUMMY"; va\_list valist; double sum = 0.0; int i; /\* initialize valist for num number of arguments \*/ va\_start(valist, num); /\* access all the arguments assigned to valist \*/ for ( i = 0; i < num; i++) { s = va\_arg(valist, num);
ERROR HERE
/home/qy/Qt/Examples/Qt-5.15.0/bluetooth/btchat/remoteselector.cpp:396: error: unknown type name 'num'ui->textEdit->append(s); } /\* clean memory reserved for valist \*/ va\_end(valist); //return sum/num;
}
-
I screwed-up and started posting code problem in "quick answers' and I am sorry for that. So I cut and paste it here to continue and hopefully resolve the issue
Not much of an improvement - more questions.
I am using the tutorial example and it is complaining about
missing "num" .
I am passing QString as variable number of parametersCopy Code
QString parameter = " TEST message ";
ProcessMessage_Variadic(1, " TEST message ");So what is the problem - the macro
Expand ▼ Copy Codeva_arg
?
declaration
void ProcessMessage_Variadic(int num,...);usage
ProcessMessage_Variadic(1, " TEST message ");definition
void RemoteSelector::ProcessMessage_Variadic (int num,...)
{ui->textEdit->append( "RemoteSelector::ProcessMessage\_Variadic"); QString s = "DUMMY"; va\_list valist; double sum = 0.0; int i; /\* initialize valist for num number of arguments \*/ va\_start(valist, num); /\* access all the arguments assigned to valist \*/ for ( i = 0; i < num; i++) { s = va\_arg(valist, num);
ERROR HERE
/home/qy/Qt/Examples/Qt-5.15.0/bluetooth/btchat/remoteselector.cpp:396: error: unknown type name 'num'ui->textEdit->append(s); } /\* clean memory reserved for valist \*/ va\_end(valist); //return sum/num;
}
Member 14968771 wrote:
error: unknown type name 'num'
That's pretty clear, I think. But here's the scoop - when pulling arguments out of a
va_list
, the second argument tova_arg
is atype
, not a variable name. So in your case this should beQString s;
for(int i = 0; i < num; ++i)
s = va_arg(args, QString)Keep Calm and Carry On
-
Member 14968771 wrote:
error: unknown type name 'num'
That's pretty clear, I think. But here's the scoop - when pulling arguments out of a
va_list
, the second argument tova_arg
is atype
, not a variable name. So in your case this should beQString s;
for(int i = 0; i < num; ++i)
s = va_arg(args, QString)Keep Calm and Carry On
-
Member 14968771 wrote:
error: unknown type name 'num'
That's pretty clear, I think. But here's the scoop - when pulling arguments out of a
va_list
, the second argument tova_arg
is atype
, not a variable name. So in your case this should beQString s;
for(int i = 0; i < num; ++i)
s = va_arg(args, QString)Keep Calm and Carry On
Where is
i
used in the call tova_arg
?The difficult we do right away... ...the impossible takes slightly longer.
-
Many thanks you saved me from hunting for the macro definition. So how would it work if the passed parameters are of mixed type ? Or is it even possible to have mixed parameters?
This is the mechanism that
printf()
uses to pass mixed arguments in, so its definitely doable. printf uses its format string to help unpack the argument list, but there are other ways. You could use a simplified format string like"sddi"
, showing that the unspecified arguments are astring
, twodouble
s and anint
. Another option might be to use an indicator e.g#define ARG_INT 1
#define ARG_LONG 2
#define ARG_DOUBLE 3
#define ARG_CHAR 4
#define ARG_STRING 5
// ...
#define ARG_END -1int var_arg_fn(int arg, ...)
{
va_ist args;
va_start(args, arg);
while(arg != ARG_END) {
switch(arg) {
case ARG_INT :
{
int i = va_arg(args, int);
// ...
break;
}
case ARG_DOUBLE :
{
double d = va_arg(args, double);
// ...
break;
}
// ... etc ...
default:
// handle error, maybe
}
arg = va_arg(args, int);
}
}
// and then call it like
var_arg_fn(ARG_INT, 1, ARG_DOUBLE, 3.2, ARG_STRING, strvar, ARG_END);I'm sure if you think about it, you can come up with something that suits your needs. But since you're using
C++
now might be the time to venture into the world ofvariadic fuction templates
. Google for that and check out one or more of the tutorials and/or examples. It might be a better fit than trying to wrap things back down to Cstdargs
. Update: Here's a video on variadic templates that may help [C++ Weekly - Ep 6 Intro To Variadic Templates - YouTube](https://www.youtube.com/watch?v=o1EvPhz6UNE&list=PLs3KjaCtOwSZ2tbuV1hx8Xz-rFZTan2J1&index=6)Keep Calm and Carry On
-
Where is
i
used in the call tova_arg
?The difficult we do right away... ...the impossible takes slightly longer.
Its only used as a loop counter. If you prefer we could do
while(num--)
{
s = val_arg(args, QString);
// ...
}That, of course alters the value of num, so if you need to know how many args were passed in, or need to traverse the argument list again, you don't want to do that.
Keep Calm and Carry On