Is it possible to have a function with variable arguments and no named argument?
For example:
SomeLogClass("Log Message Here %d").Log(5);
SomeLogClass("Log Message Here %d").Error(5);
Take a look at QString's arg methods. Those seem to be something you're looking for.
You can definitely roll your own, although implementation might turn out to be not really trivial, especially if you would like it to support printf format specifiers. If printf style is not necessary, chaining a replace_all kind of calls sounds doable.
Can you write code like that above - yes you can. But you cannot portable write a variadic function without at least one non-variadic parameter. In printf(), for example, this is the format string. In other words, you can write function s like:
int printf( const char * format, ... );
but not:
int printf( ... );
Where I am from we use this:
Log << "LogMessageHere: " << ErrorClass << 5 << whatever << std::endl;
It is not exactly an answer to you question, but it is a solution to your problem, and I think it is more c++ like.
The right answer is no, you can't define only variable arguments, because the mechanism in C/C++ to do so uses a fixed argument in order to compute an address, like this:
void f(int a, ...) {
va_list args;
va_start(args, a); // without a, this macro DOESN'T WORK!!!
}
The answer you flagged gets around it by defaulting the arguments. But what this should teach the newbies is that defaulting the arguments doesn't mean that arguments aren't passed, it means that you don't have to type them.
void f (int a = 0, ...)
So when you call f you can write:
f();
but internally, it's writing f(0)
Related
How to pass multiple string parameter in C++ without using vector and pass it like an argument?
I want to do something like this.
void MyClass::go()
{
check("string1","string2","string3");
}
//guessing
void check(string values,...)
{
//how I can output each value here?
}
EDITED:
Thanks for the answers, but my goal is to pass string paramaters with undefine sizes. it means I don't need to input some int for it size. I don't want to use vectors :)
In my opinion the best solution would be to actually use a vector. This way you have type safety, and you can pass in any number of strings.
You can also use variadic templates.
If you exactly know how many strings you want to pass in, you can have a parameter list of that many strings. This is pretty tedious though, if you change your mind you need to rewrite your function (and every code using it).
The problem with var args is that it's not typesafe, the compiler can't verify, that you want to pass in a bunch of strings to your function.
void check (const string &string1, const string &string2, const string &string3)
{
cout << string1 << " " << string2 << " " << string3 << endl ;
}
In c & c++, this can be achieved by something called variable arguments. Note that for varargs, you do need to provide atleast one argument which is the number of strings, at the time of invoking the function.
A variable argument facilitates the passing of multiple arguments, without actually knowing the number of arguments to pass.
For this, you can include stdarg.h. This gives you the data type: va_list, and associated functions:
#include <cstdarg>
#include <iostream>
using namespace std;
void check ( int num, ... )
{
va_list arguments; //a place to store the arguments values
va_start ( arguments, num ); // Initializing arguments to store all values after num
for ( int x = 0; x < num; x++ ) { // Loop until all numbers are added
cout << va_arg ( arguments, string ); // Prints the next value in argument list to sum.
}
va_end ( arguments ); // Cleans up the list
}
void MyClass::go()
{
check(3,"string1","string2","string3");
}
num is the number of arguments, that you'll provide.
va_start populates the va_list with the arguments (in this case the strings) that you provide.
va_arg() is used as to access those arguments in the list.
Finally, va_end() is used for cleaning up the va_list.
Either you may use va_list or variadic templates in C++11. It depends on your context.
I mean strings like "(%d%%%d) some text %s , %d%% %x %o %#x %#o \n". The printf family of functions somehow know how many args they would need from this string so separate argument for it is not needed. Is this functionality provided in c/c++ in terms of a separate function so I could write my own printf-like functions ? (yes I put these percents intentionally to accent how complicated it could get, so it is not simple counting of percent characters)
The problem with printf family is that it is not safe, and it doesn't really know or care how many format elements are there in string or in argument list.
printf family uses something called "variadic functions"; only one parameter is named (format string) and others are taken from the stack, without respecting their type or size - their type is deduced from format string, which makes it type-unsafe, and finds how many arguments to use by iterating over the string and finding all formatting specifiers, which makes it argument-number-unsafe. You can write variadic functions; syntax is
void foo(...);
and later you can use those macros and types, although if you are using C++, you should use C++11's variadic templates instead of C variadic functions, as variadic templates are type safe - you don't loose type information anywhere, and with universal references (but not quite thanks them) they are more powerful than variadic functions.
No, there is no standard library function for parsing printf-style format strings. If you want to write your own string formatting function, then I strongly recommend against following the printf example. It's inherently unsafe for the reasons mentioned in the others answers. It also has problems with localization since word order changes in some languages. Personally, I would write a type-safe function using templates and copying the .NET style of format strings. (Actually, I did do that--it's a lot of work but also fun.)
the printf family of functions only knows about one parameter, the first one...
It basically scans the string and each time it encounters a format specifier that it understands it pulls then next argument of that size from the argument list... this is an easily corruptible behavior.
imagine:
printf("%i",someInt); // fine
printf("%i",someLong); // depending on endianness and sized
// of those types could be the high or low 32 bits(probably)
printf("%i %i",someInt); // depending on abi could crash, read a int sized chunk
// of stack, or a register that would correspond to that
// parameter.
so inherently not safe..
you should pay attention to warnings and when writing portable code do things like:
size_t t = 5; //can be 32 or 64 bit depending on arch.
printf("%ull",(unsigned long long)t);
Edit. I guess I only half answered the question...
you can define your own variadic functions, the following adds count number of params and returns the result.
int sumList(int count, ...);
int main(int argc, const char * argv[])
{
printf("the answer is: %i",sumList(4,1,2,3,4));
return 0;
}
int sumList(int count, ...)
{
va_list args;
va_start(args, count);
int sum = 0;
for (int i = 0; i<count; i++) {
sum += va_arg(args, int);
}
va_end(args);
return sum;
}
This is my current function which works but is not type safe and can get annoying sometimes.
void Debug::Log(LogLevel level, const char* format, ...)
{
va_list args;
va_start(args, format);
cout << "[" << LogLevelToString(level) << "]\t";
vprintf(format, args);
va_end(args);
cout << endl;
}
As you can see I would like for the arguments passed in to be formatted by the format specified. I know std::cout has formatting capabilities but I haven't found anything which explains how it can be implemented with the C va_list.
Basically the main points are: I want to keep the the same behavior but with a type safe more modern method, I need to std::cout so I can easily redirect output to file or where ever I need to.
Helpful points: from the format I can determine how many parameters where passed in, is there a way to loop through va_list arguments so I can pass them to cout individually?
Thanks
For easy redirection, you can certainly use vfprintf(). For individual control/cout of each argument, I think the only way is to va_arg() through the list using the correct type, i.e. an_int = va_arg(the_va_list, int);, a_double = va_arg(the_va_list, double);, and so on. I haven't tried but I think va_arg will do the proper increment on the memory using the type passed to it.
I have been reading that some compilers support va_list with macros and users were able to overload the functionality with other macros in order to count the va_list.
With visual studio, is there a way to determine if the va_list is empty (aka count==0)? Basically I would like to know this condition:
extern void Foo(const char* psz, ...);
void Test()
{
Foo("My String"); // No params were passed
}
My initial thought was to do something like this:
va_list vaStart;
va_list vaEnd;
va_start(vaStart, psz);
va_end(vaEnd);
if (vaStart == vaEnd) ...
The problem is that va_end only sets the param to null.
#define _crt_va_start(ap,v) ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )
#define _crt_va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define _crt_va_end(ap) ( ap = (va_list)0 )
I was thinking of maybe incorporating a terminator but I would want it to be hidden from the caller so that existing code doesnt need to be changed.
There is no way to tell how many arguments are passed through ..., nor what type they are. Variadic function parameters can only be used if you have some other way (e.g. a printf-style format string) to tell the function what to expect; and even then there is no way to validate the arguments.
C++11 provides type-safe variadic templates. I don't know whether your compiler supports these, or whether they would be appropriate for your problem.
I realize this question is fairly old, but I thought it might be helpful to flesh it out a bit. As Mike Seymour answered quite correctly, there is no absolutely reliable way to determine the number of arguments in a va_list. That's why the conventional way to define a variadic function is to include a parameter that has that information, like so: void func(const char *str, int count, ...);, which defines a contract your callers are supposed to abide by.
EDIT: The standard (7.16.1.1.3) is actually silent on the value returned by va_arg(vl, type) for any call past the end of the variable argument list. The most common case for most types is typed-zero. However, CAVEAT EMPTOR - it doesn't have to be.
The value returned from va_arg(vl, type) when there are no more arguments is a typed-zero value. For numeric types, it is 0. For pointers, it is a NULL pointer. For structs, it is a struct with all fields zeroed. If you elect to copy the va_list and try to count the copy, like so:
void func(const char *str, ...) {
va_list vl;
va_list vc;
int x;
int count;
count = 0;
va_start(vl, str);
va_copy(vc, vl);
do {
x = va_arg(vc, int);
if (x == 0) break;
count++;
} while (1)
va_end(vc);
.
.
. // do something, or something else,
. // based on the number of args in the list
.
va_end(vl);
You would have to make the assumption that the caller would abide by the contract not to pass a NULL or zero value in the list. Either way, you have to understand that the caller of a variadic function is responsible for abiding by the stated contract. So write your function, publish the contract, and sleep easy.
I am aware that my answer isn't an "orthodox" answer, however due to the limitation of the va_list macro, I found the following solution to work. We can look at a va_list as an array of chars, and even better, a null terminated one, so you can try
va_list argptr;
if(strcmp(argptr,""))
{
// not empty
}
else
{
// empty
}
I tried that and it worked for me.
I used Visual Studio 2013 Ultimate. The project type is Win32 Console Application. No compilation errors.
I have a function with following signature
char requestApiCall(int num, const wchar_t* pParams = 0, ...)
{
...
}
Now I want to to get all pParams in an array (or to be able to iterate over it). I know this is possible with some macros, but I have no idea how to do it.
Any help would be appreciated.
P.S. I'm using MinGW if it matters.
UPDATE
my question caused confusion. I will try to clarify (sorry for my grammar). Both Object Pascal and C# has the ability to pass unlimited amount of parameters to a method. In C# we achieve this with params keyword:
void Foo(params string[] strs)
{
...
}
Foo("first", "second", "another one", "etc");
I want to achieve same result in C++ without using any object/class. In my case, type safety is not a concern, but if there is a type safe way to achieve that goal, I will gladly hear your comments :)
Thanks
You need to look at the functions and macros declared in stdarg.h. Here is a tutorial that explains it.
http://publications.gbdirect.co.uk/c_book/chapter9/stdarg.html
I'm not sure what your function parameters are supposed to represent but I think you'll find that it needs to change.
By the way, I find that for C++ I can usually avoid variadic functions. This has the advantage of preserving type safety. Are you sure you really need a variadic function?
Using variadic function arguments is a dangerous and tricky business, and almost surely there is a better way - for example, you might pass an std::vector<std::wstring>& to your function!
OK, that said, here's how to use variadic arguments. The key point is that it is your responsibility to know the number and types of the arguments!
#include <cstdarg>
char requestApiCall(int num, const wchar_t* pParams, ...)
{
va_list ap; // the argument pointer
va_start(ap, pParams); // initialize it with the right-most named parameter
/** Perform magic -- YOU have to know how many arguments you are getting! **/
int a = va_arg(ap, int); // extract one int
double d = va_arg(ap, double) // one double
char * s = va_arg(ap, char*) // one char*
/* ... and so forth ... */
va_end(ap); // all done, clean up
}
Just for completeness, I would redefine the function as this:
char requestApiCall(std::vector<std::wstring> & params)
{
for (std::vector<std::wstring>::const_iterator it = params.begin(), end = params.end(); it != end; ++it)
{
// do something with *it
}
/* ... */
}
A good example of what you are trying to accomplish is the exec family of functions. exec() takes an variable list of arguments all of which are expected to be const char*. The last item is a NULL ((char*)0). The last item is the indicator for when the list of items is complete.
You can use the variadic macros in stdargs.h as others have described.