Unknown number of arguments in function [duplicate] - c++

This question already has answers here:
Variable number of arguments in C++?
(17 answers)
Closed 9 years ago.
I've got the class member:
LineND::LineND(double a ...)
{
coefficients.push_back(a);
va_list arguments;
va_start(arguments, a);
double argValue;
do
{
argValue = va_arg(arguments, double);
coefficients.push_back(argValue);
}while(argValue != NULL); // THIS IS A PROBLEM POINT!
va_end(arguments);
}
I don't know how many arguments will be used. I need to take each argument and put it into the vector called coefficients. How should I do that? I understand, that the statement while(argValue != NULL) is not correct in this case. I can't use for example this signature:
LineND::LineND(int numArgs, double a ...)
to change the condition like this:
while(argValue != numArgs);
The point is I can't change the signature of the method. Need to resolve this problem another way.

Variable argument lists have several drawbacks:
Callers can pass in everything they want.
If a non-POD object is passed, undefined behaviour is summoned
You can't rely on the number of arguments (the caller can make errors)
You put a LOT of responsibility on your CLIENT, for whom you intended to have an easier time with your library code (practical example: format-string-bugs/-errors)
Compared to variadic templates:
Compile time list size is known
Types are known at compile time
You have the responsibility for stuff, not your client, which is like it should be.
Example:
void pass_me_floats_impl (std::initializer_list<float> floats) {
...
}
You can put this into the private section of a class declaration or in some detail namespace. Note: pass_me_floats_impl() doesn't have to be implemented in a header.
Then here's the nice stuff for your client:
template <typename ...ArgsT>
void pass_me_floats (ArgsT ...floats) {
pass_me_floats_impl ({floats...});
}
He now can do:
pass_me_floats ();
pass_me_floats (3.5f);
pass_me_floats (1f, 2f, 4f);
But he can't do:
pass_me_floats (4UL, std::string());
because that would emit a compile error inside your pass_me_floats-function.
If you need at least, say, 2 arguments, then make it so:
template <typename ...ArgsT>
void pass_me_floats (float one, float two, ArgsT... rest) {}
And of course, if you want it a complete inline function, you can also
template <typename ...ArgsT>
void pass_me_floats (ArgsT... rest) {
std::array<float, sizeof...(ArgsT)> const floaties {rest...};
for (const auto f : floaties) {}
}

Variadic arguments are heavily frowned upon in C++, and for good reason. One of these reasons is that there is no way to know where the list ends, so if you can't change the signature of the function, you must dictate some kind of sentinel value to indicate where the list ends. If you cannot do either of those things, you are screwed.

You should rewrite the method to take std::initializer_list<double>.
If you can't do that, and can't add a count parameter, the fix is to take a sentinel value that terminates the argument list, e.g. 0.0 or NaN (or any value that doesn't make sense in your function's context).
For example, functions that take a variable number of pointers use NULL as the sentinel value; functions that take a list of structs take a 0-initialised struct as the sentinel. This is fairly common in C APIs; see http://c-faq.com/varargs/nargs.html where the example given is execl("/bin/sh", "sh", "-c", "date", (char *)NULL);

In this case, you cannot determine the number of arguments in your code. You have to make the caller of such function pass the number of doubles to you (I'm assuming the first a argument doesn't contain the number of arguments). Eg.:
LineND::LineND(unsigned count, ...)
{
va_list arguments;
va_start(arguments, a);
and the condition becomes
while (a--) { ... }
In C++11, you can use two better devices for passing unspecified number of doubles.
passing a vector and initializing it with an initializer-list
variadic templates
Note that there are differences between the two; tho former has some problems when forwarding originating from the fact that {...} is not an expression in C++. The latter can cause code bloat, because it generates a function for each combination of argument types.
In C++03, you can only use helper objects, such as those offered by the Boost.Assignment library, for passing unknown number of arguments.

Make the first double of the arguments list be the actual count of arguments.

Related

is there a GCC -W* option that would alert me when I'm providing wrong argument for va_list? [duplicate]

I'm currently writing a function which will take a variable number of arguments. I pass the number of arguments into the function and then will iterate through the arguments list.
Each of the passed arguments should be an integer. I will be adding this integer to a vector of integers which will be used later.
I would like to make sure that some joker doesn't attempt to pass this function something other then an integer in the future. I recognize that I can check the current argument from va_arg to ensure it is not NULL and I can use something like isanum(va_arg()) to determine if it is a valid integer. I suppose I could even check the sizeof(va_arg) and compare it against the sizeof(int) and ensure they are equal.
Are there any other checks which I can run to verify I have been passed a valid integer?
Thanks in advance for assistance
There is no sensible way you can do this. Variable-argument functions work by concatenating all the raw binary representations of the arguments into one big chunk of data on the stack. So it relies on both the caller and the callee agreeing on what the number and type of arguments are (otherwise you'll end up reading e.g. an int as if it were a float).
As to your specific ideas:
va_arg() is a macro that simply interprets some number of bytes of the raw stack data as whatever type you specify. So invoking sizeof() on it will simply tell you the size of the data type you asked for.
In general, there are no patterns of raw binary data that form an invalid integer. So the hypothetical isanum() could not work.
Each of the passed arguments should be an integer.
If you have a C++0x compiler, I suggest an initializer_list<int> instead of varargs:
#include <initializer_list>
void foo(std::initializer_list<int> numbers)
{
my_vector.insert(my_vector.end(), numbers.begin(), numbers.end());
}
int main()
{
foo( {2, 3, 5, 7} );
}
This is straight-forward and completely type-safe.
Each of the passed arguments should be
an integer. I will be adding this
integer to a vector of integers which
will be used later.
Then why not just accept a vector of integers?
void AddIntegers(const std::vector<int>& vec);
You can then always concatenate vectors together using iterators.
Or make an interface like this:
void AddInteger(int newInt);
Or even this:
void AddIntegers(const int* integers, unsigned int numIntegers);
template <unsigned int Size>
void AddIntegers(int (&integers)[Size])
{
AddIntegers(integers, Size);
}
int main()
{
int i[] = {1, 2, 3, 4};
AddIntegers(i);
}
These will work if you need to work with a C++03 compiler. If you have a C++0x compiler, there are far superior solutions available.
Variable arguments are unsafe by design. You cannot check that the user passed correct type in any way. C++0x comes to the rescue with variadic templates but not many compilers support it nowadays (only GCC afaik).
Unfortunately, there really isn't a way to do this. Functions like printf() can easily be fowled up by passing invalid or the wrong number of arguments.
In C++, this is an advanced feature that requires the programming using such code to ensure the correct arguments are passed.
You can't do any sort of type checking with varargs. I'd suggest using an iterator range instead (like standard library functions) or possibly a std::vector<int>. This way the types can't be subverted.
Since you are using C++, how about overloading some operator and pass the arguments one-by-one? For example
class MyFunction {
std::vector<int> param;
public:
MyFunction() { /* some initialisation? */ }
MyFunction &operator,(int eatMe) {
param.push_back(eatMe);
return *this;
}
~MyFunction() {
//the implementation of your function goes here
}
}
Then you can call it like this:
MyFunction(),2,3,5,7;
Note, the use of comma operator may look scary, but it is actually very helpful in this case. It is the lowest possible, left-associative operator.
If your function takes some extra parameters, not only the unknown-length of int-s, you can pass them in the constructor.
If someone uses something else than int, the default comma operator will be used (evaluate left side, discard, evaluate right side). If you don't like that - pick a different operator, e.g. stream-like << or boost-like %.
If you are restricted to C++03 and all your arguments should be integers, one solution would be to simply hide the variable argument function (in a 'detail' namespace for example) and make a series of overloaded functions for 1 to N amount of arguments. Those functions would be simple inline functions that forward the call to the vararg version of the real function. This way, you have one real implementation, no run-time overhead, and you expose a type-safe interface to the caller (and the caller can always use the vararg version if he needs more than N arguments).
Boost.PP can also help to generate these types of repetitive patterns.
Of course, if you have some level of C++0x support, than the problem can be solved in many ways, including initializer_list or variadic templates.
Just to illustrate my comment on CygnusX1's answer, you could do it like:
class MyFunction {
std::vector<int> params;
public:
MyFunction() { (*this)(); }
MyFunction(int eatMe) { (*this)(eatMe); }
MyFunction& operator()(int eatMe) {
params.push_back(eatMe);
return *this;
}
void operator()() {
// use params to do something interesting
}
}
MyFunction(2)(3)(5)(7)();

Can I differentiate between one and multiple arguments?

Is there any new facility in C++11 or C++14 that allows us to stop having to use:
TRACE0("one-string-no-args");
and
TRACE("formatting string with one-or-more args", arg1, arg2, etc);
Such functions have had to be differentiated by name, because overloading can't distinguish the zero-additional-arguments case from one-or-more-arguments case, to the best of my knowledge.
This of course matters for printf style interfaces, where being able to know that there aren't anymore arguments means you can avoid a class of bugs by not trying to interpret the formatting string as a formatting string, but only as a final output string.
You probably just don't know the name of the feature: variadic templates.
Its main use is to deduce a variable number of types from a variable number of arguments; you can either store it all somewhere (like std::make_tuple()), or just open the arguments to use them.
Here's a basic usage:
void print() {}
template<class Head, class... Tail>
void print(Head h, Tail... t)
{
cout << h << endl;
print(t...);
}
int main()
{
print(3, "hello", 4.5);
}
See it in action here: http://ideone.com/VA7YGK
As you can see it looks like functional programming (because it is!), where you match against a rule that splits the list of arguments into a head and a tail, and then invoke itself with one less element.
Another example, from a recent question, where I defined a data structure recursively (short and simple enough to be readable): Multikey map using variadic templates
The std::thread constructor is another example, it takes a variable number of arguments to give them to the function once it starts running in the spawned thread; just about everything new in C++11 that interacts with functions (e.g. std::function) uses variadic templates so they can accept any number of arguments of any type. std::tuple, std::make_tuple() and std::tie() also make use of it.
Searching the web you'll find plenty of more advanced usages. Pay special attention to the rules for the argument expansion, and perfect forwarding.
For the TRACE macros (which are typically included in Microsoft's debugging macros), no, the language will not have a "new" method for handling preprocessor macros (it is effectively the same as it has been).
For functions in general, variadic functions have always been supported (e.g. printf).
This may seem foolish to some - but I have a metric ton of C-style printf code to maintain.
We could rebuild it all using boost's formatting libraries, and perhaps we'll get to it one of these days. However, in the meantime, just being able to distinguish on one argument, or one + one-or-more arguments is a huge step forward.
https://stackoverflow.com/users/365496/bames53 noted that is is possible to do so, and it appears to work (at some possible expense in code bloat, and with the caveat that this is still printf land with all of its pitfalls).
Here is a simple example that does it's job in MFC/C++:
bool Write(const wchar_t * pszText);
template <typename T> bool Write(const wchar_t * pszFormat, T, ...);
Write need not (and should not) call vwsprintf equivalent, while Write<> does do so in order to build the output string before passing it on to Write.
Very elegant. Removes the problem of either only providing the second interface (and then you get printf problems if your one string happens to have an accidental printf format specifier in it), or forcing clients to specify Write() vs. WriteFormat() or similarly do the string construction locally before calling Write().
Here's Write<> defined in terms of Write:
template <typename T> bool SimpleTextFile::Write(const wchar_t * pszFormat, T, ...)
{
va_list arglist;
va_start(arglist, pszFormat);
CStringW buffer;
buffer.FormatV(pszFormat, arglist);
va_end(arglist);
return Write(buffer);
}

Pass an object as parameters to a function in C++

In Javascript or ActionScript it's possible to pass an object to a function or a constructor.
myfunction({myParam:1, myOtherParam:"hello"});
It is very useful when you have a lot of parameters to pass, IMO it makes using functions easier than using the classic approach.
myFunction(1,"hello");
Is there something similar in C++?
TIA
boost parameter http://www.boost.org/doc/libs/release/libs/parameter/ do exactly what you want.
From its abstract:
Use this library to write functions and class templates that can
accept arguments by name
Small example:
// include boost parameter
#include <boost/parameter/keyword.hpp>
namespace parameter = boost::parameter;
// first declare named parameters
BOOST_PARAMETER_NAME(a) // Note: no semicolon
BOOST_PARAMETER_NAME(b)
// then declare your function
BOOST_PARAMETER_FUNCTION(
(int), // 1. parenthesized return type
my_function, // 2. name of the function
tag, // 3. namespace of tag types (don't change!)
(required (a, int) ) // 4. one required parameter of type int
(optional // and an optional parameters, with default value
(b, int, 0)
)
)
{
return a + b;
}
// then you can call it with no named parameters
int result = my_function(1, 2);
// or with named parameters
int result = my_function(_a=1, _b=2);
// also with optional parameters omitted
int result = my_function(_a=3);
You can use the "named parameter idiom":
http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.20
Which would make your call look like:
f(1).myOtherParam("Hello")
See here for a comparison with Boost parameter.
One could use structures:
struct foo {
int a,b,c;
float f;
}
Sadly, you need to define them somewhere and the receiving function needs to accept them, you can't just make them up in-place.
At the end of the day, there's no language tool in C++ that could mimic the JavaScript 'idiom'. Such stuff lies in the nature of a dynamic language, which C++ is not.
Yes.
In C++, an object is an instance of a class. You could create a class holding all the possible arguments, instantiate it and fill it with your particular values, and then pass that instance to the function.
You cannot just pass an arbitrary object instead of the function's arguments, because C++ doesn't have named arguments - only the position matters, and the position within some kind of hash structure is lost. So you can't say foo(y=3) when you have a function foo(int x, int y) because the names x and y only have meaning within the function - not to its callers.
No, not really. There is a map class in the standard library, and of course you could write a function that accepted a map full of named values as input, but there's nothing that exists directly as a language feature equivalent to what you've shown.
As several other posters have pointed out, of course you can define a class to hold all the data values, but this just pushes the ordered parameter list from the function to the constructor of that object, so it buys you nothing at all.
Use structs or classes to group your data.
If you're looking for a way to pass key value pairs, use STL maps
Not at the language level, but:
It is very useful when you have a lot of parameters to pass, IMO it makes using functions easier than using the classic approach.
You should really consider cutting down on your parameters if you can. Often this can be achieved by using aggregates:
Example:
draw_rectangle(x1, y1, x2, y2, r, g, b, a)
Could be reduced to:
draw_rectangle(p1, p2, color)
Or even further:
draw_rectangle(rect, color)
The temptation for named parameters should be mitigated considerably if you do this.
You can also use alternative approaches like Boost Parameter which, through a lot of template magic, accomplishes something like this. However, it requires you turn all your functions using this technique into templates written in a very precise way, and it's a very bulky and heavy-handed attempt to force the language to do something it wasn't designed to do if you ask me.
You can do the following, which supports default values to a limited amount (limited by the template system of C++). You will need to compile this with the newest standard (C++11)
// used to skip arguments and default to the previously specified value
struct UseDefault {
// empty intentionally!
};
// using this is optional, and only required if you want to provide default values by the CALLED function
template <typename T, T def> struct Default {
T value;
operator T() {
return value;
}
Default(T value) : value(value) {}
Default(UseDefault ignore) : value(def) {(void)ignore;}
};
// using tuple, you can bundle any number of parameters to one
int myFunc(std::tuple<Default<int,7>,Default<char,'x'>,std::string> parameters) {
std::cout << std::get<0>(parameters) << ", " << std::get<1>(parameters) << std::endl;
return 0;
}
You can then invoke myFunc like this:
func(std::make_tuple(6,UseDefault(),"hi"));
Note however, that there are some limitation to the template parameter types, for instance, you cannot pass strings (or char*s for that matter) as template parameters. However, if you only need reasonable basic default values, this could work.
Of course if you drop your requirement to specify default values, you can simply use the std::tuple without my Default type.

Verifying variable arguments are of expected type

I'm currently writing a function which will take a variable number of arguments. I pass the number of arguments into the function and then will iterate through the arguments list.
Each of the passed arguments should be an integer. I will be adding this integer to a vector of integers which will be used later.
I would like to make sure that some joker doesn't attempt to pass this function something other then an integer in the future. I recognize that I can check the current argument from va_arg to ensure it is not NULL and I can use something like isanum(va_arg()) to determine if it is a valid integer. I suppose I could even check the sizeof(va_arg) and compare it against the sizeof(int) and ensure they are equal.
Are there any other checks which I can run to verify I have been passed a valid integer?
Thanks in advance for assistance
There is no sensible way you can do this. Variable-argument functions work by concatenating all the raw binary representations of the arguments into one big chunk of data on the stack. So it relies on both the caller and the callee agreeing on what the number and type of arguments are (otherwise you'll end up reading e.g. an int as if it were a float).
As to your specific ideas:
va_arg() is a macro that simply interprets some number of bytes of the raw stack data as whatever type you specify. So invoking sizeof() on it will simply tell you the size of the data type you asked for.
In general, there are no patterns of raw binary data that form an invalid integer. So the hypothetical isanum() could not work.
Each of the passed arguments should be an integer.
If you have a C++0x compiler, I suggest an initializer_list<int> instead of varargs:
#include <initializer_list>
void foo(std::initializer_list<int> numbers)
{
my_vector.insert(my_vector.end(), numbers.begin(), numbers.end());
}
int main()
{
foo( {2, 3, 5, 7} );
}
This is straight-forward and completely type-safe.
Each of the passed arguments should be
an integer. I will be adding this
integer to a vector of integers which
will be used later.
Then why not just accept a vector of integers?
void AddIntegers(const std::vector<int>& vec);
You can then always concatenate vectors together using iterators.
Or make an interface like this:
void AddInteger(int newInt);
Or even this:
void AddIntegers(const int* integers, unsigned int numIntegers);
template <unsigned int Size>
void AddIntegers(int (&integers)[Size])
{
AddIntegers(integers, Size);
}
int main()
{
int i[] = {1, 2, 3, 4};
AddIntegers(i);
}
These will work if you need to work with a C++03 compiler. If you have a C++0x compiler, there are far superior solutions available.
Variable arguments are unsafe by design. You cannot check that the user passed correct type in any way. C++0x comes to the rescue with variadic templates but not many compilers support it nowadays (only GCC afaik).
Unfortunately, there really isn't a way to do this. Functions like printf() can easily be fowled up by passing invalid or the wrong number of arguments.
In C++, this is an advanced feature that requires the programming using such code to ensure the correct arguments are passed.
You can't do any sort of type checking with varargs. I'd suggest using an iterator range instead (like standard library functions) or possibly a std::vector<int>. This way the types can't be subverted.
Since you are using C++, how about overloading some operator and pass the arguments one-by-one? For example
class MyFunction {
std::vector<int> param;
public:
MyFunction() { /* some initialisation? */ }
MyFunction &operator,(int eatMe) {
param.push_back(eatMe);
return *this;
}
~MyFunction() {
//the implementation of your function goes here
}
}
Then you can call it like this:
MyFunction(),2,3,5,7;
Note, the use of comma operator may look scary, but it is actually very helpful in this case. It is the lowest possible, left-associative operator.
If your function takes some extra parameters, not only the unknown-length of int-s, you can pass them in the constructor.
If someone uses something else than int, the default comma operator will be used (evaluate left side, discard, evaluate right side). If you don't like that - pick a different operator, e.g. stream-like << or boost-like %.
If you are restricted to C++03 and all your arguments should be integers, one solution would be to simply hide the variable argument function (in a 'detail' namespace for example) and make a series of overloaded functions for 1 to N amount of arguments. Those functions would be simple inline functions that forward the call to the vararg version of the real function. This way, you have one real implementation, no run-time overhead, and you expose a type-safe interface to the caller (and the caller can always use the vararg version if he needs more than N arguments).
Boost.PP can also help to generate these types of repetitive patterns.
Of course, if you have some level of C++0x support, than the problem can be solved in many ways, including initializer_list or variadic templates.
Just to illustrate my comment on CygnusX1's answer, you could do it like:
class MyFunction {
std::vector<int> params;
public:
MyFunction() { (*this)(); }
MyFunction(int eatMe) { (*this)(eatMe); }
MyFunction& operator()(int eatMe) {
params.push_back(eatMe);
return *this;
}
void operator()() {
// use params to do something interesting
}
}
MyFunction(2)(3)(5)(7)();

C++ newbie question: designing a function to return a vector of either string or double--overload or template?

I have written a function that searches a text file for names. It returns vector, where each element of the vector is a different name.
Now I would like to search the same text file for numbers and return the numbers in a vector.
This is probably a dumb question, but I'm wondering what the best approach would be. Overload the function by writing a second function that returns a vector or turning the function I have already written into a template by replacing the type with T, as in vector.
The reason I'm confused about the template option is that I'm not sure if strings and numerical types like double and int are compatible in a template. Any tips would be appreciated! Thanks.
As a function signature does not include its return type, you can't overload a function only on its return type.
Also, as the two functions returns different kind of data (one could return person names, the other could return the persons ages), having the same name for both seems a semantic error.
But anyway...
Move the return type part back into the signature
void retrieveData(std::vector<std::string> & data) ;
void retrieveData(std::vector<double> & data) ;
void foo()
{
std::vector<std::string> strings ;
std::vector<double> doubles ;
// retrieve the strings
retrieveData(strings) ;
// retrieve the numbers
retrieveData(doubles) ;
}
This solution is best both because the overload work "as is", and because it avoids a copy of the vector (I am using C++03, here... In C++0x, one would use move semantics to avoid the potential extra copy).
Make the return type part of the signature (non-template version)
std::vector<std::string> retrieveData(std::string * dummy) ;
std::vector<double> retrieveData(double * dummy) ;
void foo()
{
// retrieve the strings
std::vector<std::string> strings = retrieveData((std::string *) NULL) ;
// retrieve the numbers
std::vector<double> doubles = retrieveData((double *) NULL) ;
}
Here, the dummy parameter's pointer value is not used in the function body. It's use is to enable the compiler to find the right overload.
This is ugly (not mentioning the part on returning by copy a vector in C++03 but this is out of topic), but it does the work and is a viable answer to your question.
Make the return type part of the signature (template version)
// declared, but not defined
template<typename T>
std::vector<T> retrieveData() ;
// defined
template<>
std::vector<std::string> retrieveData<std::string>() ;
// defined
template<>
std::vector<double> retrieveData<double>() ;
void foo()
{
// retrieve the strings
std::vector<std::string> strings = retrieveData<std::string>() ;
// retrieve the numbers
std::vector<double> doubles = retrieveData<double>() ;
}
Here, the template parameter is given by the user, thus giving the compiler enough information to choose the right overload
P.S.: This answer is quite similar to the one I gave here: Overload a C++ function according to the return value
I'd just make two different functions with different names like findStrings() and findNumbers(). Overloading by return type doesn't work, templates make no sense here, and, most importantly, these functions just do different things.
However, if overloading is desired, I would do it like this:
bool findInFile(const std::string &fileName, std::vector<int> &result);
bool findInFile(const std::string &fileName, std::vector<std::string> &result);
This way overloading will work, and it also has a nice property of returning success or failure indicator if you want to avoid throwing exceptions in case of failure. Just replace it with void otherwise. But this approach has the disadvantage of being awkward to use if you need not to store the result in a variable, but pass it to some function for example.
Since you have only 1 overload to do, I would go with function overload instead of templates. I think that in this case it doesn't justify adding a bunch of code just to overload a function once.
There is maybe a case for a template function as follows:
template <typename T, typename OutputIterator>
void readTokens<T>(OutputIterator oi) {
for each token in the file {
std::stringstream ss(token);
T t;
if (ss >> t) {
*oi++ = t;
}
}
}
Then you can do readTokens<string>, readTokens<int>, readTokens<double>, or any other type you care to invent in future that has a stream extraction operator (and whose string representation doesn't contain spaces, or whatever else it is you use to delimit items in your text file).
This only applies if the means of splitting up the file into tokens/items is the same regardless of the type that they're going to be read as. The reason I say "maybe" is that it might be better to first read the file into strings in a non-template function, then have a separate template function that tries to convert them to int/double/whatever, filtering out the ones that fail to convert. You'll note that the above code isn't terribly efficient with T = string, and frankly having written it you're unlikely to test it with any types other than the two you're currently interested in (int and string), so you could be storing up trouble for later.
I've made a second change to your function interface, which is to write the results to an iterator rather than returning a vector by value. This is an independent change, but it's a common trick with template functions because it means the caller can have the results written to a vector, or any other container they prefer, or perhaps process them without storing them all at once (for example if all that's needed is to write them to a stream). To get the original behavior, with the results in a vector, you'd call it like this:
std::vector<int> v;
readTokens<int>(std::back_inserter(v));
Templates would make no sense here, because the code for the function (presumably) depends on its argument type. So you would have to specialise the template anyway, and you might as well just use overloading for this.