Can I differentiate between one and multiple arguments? - c++

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);
}

Related

Reasons for using Variable Argument Lists versus vector (c++)

I am trying to understand Variable Argument Lists (varargs). I have previously used pointers and/or std::vector for parameters which can change in the amount of objects that need to be passed.
I would expect that Varargs (1,2) and Vectors (3,4) as part of function parameters both have their own special uses in C++ and are better at different things. However, I am having a difficult time distinguishing when std::vector is not the right choice. Could this please be explained?
Is this the type of scenario where varargs might be preferred?
union S //Using union from http://en.cppreference.com/w/cpp/language/union
{
std::int32_t n; // occupies 4 bytes
std::uint16_t s[2]; // occupies 4 bytes
std::uint8_t c; // occupies 1 byte
}; // the whole union occupies 4 bytes
int myFunction(std::vector<S> v)
std::printf is a great example!
The reason why varargs are used for std::printf is usability, especially for the programmer.
Why do you have to create a vector to call std::printf. It's just a pain.. Also, you would have to pass the parameters in groups of their respective types, because std::vector can't store different types:
//This would be horrible!
std::vector<std::string> text{ "Your age is" };
std::vector<std::string> text2{ "!" };
std::vector<int> age{ 26 };
//....
std::bad_print(text);
std::bad_print(age);
std::bad_print(text2);
Here it is obvious that varargs (or variadic templates, same thing) would be much better, and increase productivity, speed and memory:
//Much better
std::printf("%s %i %s", "Your age is ", age, "!");
//Even better
std::good_print("Your age is ", age, "!"); //Uses varargs or variadic templates
So, it depends. If you know how many arguments you are going to pass to the function at compile time, then use varargs (or variadic templates), because there is no reason in creating a seperate std::vector to store those values.
If you don't know the values, such as when the user inputs them, then using a std::vector is appropriate.
varargs is for when the caller has a fixed set of things in mind and the called function will take anything. like printf
printf(".....", foo, wiz, count);
I dont need this one invocation to take different numbers of parameters. Also varargs is much clearer if the args are of different types
Unless you have a virtual function, or you're pre-C++11, I'd suggest against varargs and for template parameter packs ( http://en.cppreference.com/w/cpp/language/parameter_pack ). They achieve the same goal, but parameter packs are type-safe and you don't need two sets of functions when a varargs calls another varargs. Also, variants instead of unions if you have boost.
The other thing, if you call a virtual function from your varargs function (and pass va_list), the implementation might parse a type from it that your compilation unit doesn't even know of. Thus you can't specify a finite union all the times.

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)();

function overloading vs function templates - C++

In books on C++, why are we taught to use function overloading when we have templates at our disposal in C++?
Wouldn't it be better to show the effective (and correct) use of templates? As opposed to where function overloading is taught in most books on C++?
Or, are there good reasons to use one instead of the other?
Templates provide an advantage when you want to perform the same action on types that can be different. A simple example:
template <typename T>
T foo(const T& a, const T& b) { return a + b; }
You can use overloading when you want to apply different operations depending on the type:
struct Foo{ void foo() const {} };
void foo(int i) { std::cout << "i = " << i << "\n"; }
void foo(const Foo& f) { f.foo(); }
You could achieve the above using templates and template specializations, but such specializations should represent a few exceptions to the general case.
Templates cannot take varying numbers of arguments. Overloads can. In addition, a template indicates that you can operate on any data type, but it's pointless to represent this when in fact, the vast, vast majority of templates would be specializations only (in your system). Also, overloads can be virtual and template specializations cannot. Nor can specializations differ in their signatures from the base.
template<typename T> void foo(T& t);
template<> void foo<std::string>(std::string* ptr); // Illegal
void foo(std::string* ptr); // Legal
This would severely constrain what kinds of overload you could produce compared to the current system.
You generally use templates when you want to do the same set of operations on many different data types.
You generally would use function overloading when you want to do different operations on certain sets of data.
the advantage of templates in a situation where you want to do the same set of operations on many different data types, is that the compiler will handle for you at compile time any possible new type you may create in the future that uses the templated function. if you were to use function overloading, you'd have to create a new function overload every time you created a new type that you wanted to pass to the specific function.
Just an addition to juanchopanza's answer:
With function overloads you can also vary the number of arguments, which can be handy.
A simple example, if you have some function with the following declaration:
void foo(int i, int j);
But you often call foo with first argument 0, you could write the following function which saves you some typing.
void foo(int j) {
foo(0, j);
}
Templates (normally) require that you use identical syntax to carry out the operations on all (supported) types.
Function overloading is (or should be) used similarly, but allows you to use different syntax to carry out the operations for different types. That is to say that (although you don't have to) you can represent the values in different ways. One obvious example would be what are called atan and atan2 in the C library. With atan, we pass the ratio of the "rise to the "run", and we get back the angle that ratio represents. With atan2 we pass the values for the rise and run separately (which computes roughly the same result, but since it's given slightly more input data, can produce a more complete result as well).
Although these are implemented as entirely separate functions in C, if they were written in C++ from the beginning it would be entirely appropriate to use a single name (e.g., atan) overloaded for both a one and two parameters:
double atan(double); // equivalent to current atan
double atan(double, double); // equivalent to current atan2
Templates (short of specialization, which is pretty much just overriding what templates themselves provide) doesn't provide for differences in calling syntax like this.
Overloading is also more constrained -- you provide one overload for each specific type you want to support (though if you take a pointer or reference those can also support derived types). With templates, a single template can (at least potentially) apply to any type.
So both overloading and template have their equal use .
one line difference to about them is:
overloading is used when we have various functions , doing SIMILAR operations .
template is used when we have various functions , doing IDENTICAL
operations .
There is very big differnce between "SIMILAR" and "IDENTICAL".

Unknown number of arguments in function [duplicate]

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.

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)();