Reputation: 2598
Alright, I'm pretty sure that this has been discussed before in some way or another, but I'm apparently too stupid to find it.
First: I'm NOT looking for va_list and the other macros. What I am looking for is something like the main-function parameters.
The default prototype, as all of you know is:
int main(int argc, char *argv[]);
Now, I want something similar for my program, but don't know how exactly.
Let's assume we have this function:
void Function(int argc, unsigned short *args[]) {
for(int i = 0; i < argc; ++i) printf("%hu ", args[i]);
}
And I want something like this function call:
Function(5, 1, 2, 3, 4, 5);
Would that work? Because I don't want the 'cluttering' of va_list, nor do I want to create:
void AnotherFunction() {
unsigned short Args[] = { 1, 2, 3, 4, 5 };
Function(5, Args);
}
Simply because in that case I would only need a simple pointer. Could someone please point me in the right direction? Thank you very much.
Edit: Thank you everyone for your valuable input. I'll settle for 'Doesn't work with standard C/C++ for now and look for a different approach to my problem.
Again, thank you very much.
Upvotes: 5
Views: 614
Reputation: 545923
Here are two standard C++ solutions. Both require a C++11 supporting compiler:
#include <iostream>
#include <algorithm>
#include <vector>
#include <iterator>
#include <utility>
template <typename T, typename... Us>
struct first_of_helper {
typedef T type;
};
template <typename... Ts>
using FirstOf = typename first_of_helper<Ts...>::type;
template <typename... Ts>
void f(Ts&&... args) {
typedef FirstOf<Ts...> T;
std::vector<T> v_args{std::forward<Ts>(args)...};
std::copy(v_args.begin(), v_args.end(), std::ostream_iterator<T>(std::cout, " "));
std::cout << "\n";
}
template <typename T>
void g(std::initializer_list<T> args) {
std::copy(args.begin(), args.end(), std::ostream_iterator<T>(std::cout, " "));
std::cout << "\n";
}
int main() {
f(1, 2, 3, 4);
g({1, 2, 3, 4});
}
Before C++11, the only portable solution is via va_args
. Consider: if va_args
weren’t needed because you could write simpler code, why would it exist in the first place?
Upvotes: 1
Reputation: 55425
A g++ specific solution:
const size_t MAX_ARGS = 42;
void Function(int argc, const unsigned short (&args)[MAX_ARGS])
{
}
int main()
{
Function(5, {1,2,3,4,5});
}
If you don't actually need the argc
parameter, you can write a template:
template<size_t N>
void Function(const unsigned short(&args)[N])
{
// use N
}
This works in C++03. The array needs to be const, or else you can't pass a temporary initializer list like that. If you need to modify the elements inside the function, you'll need to make a copy.
Upvotes: 3
Reputation: 83557
There are basically two ways to do variable arguments in C++:
The varargs syntax inherited from C which uses va_list, etc.
Creating container to pass in the arguments. This container can be an array, std::vector, std::list, etc.
Your proposed solution by passing the parameters directly and allowing the compiler to construct the container is very Java-esque. This is how Sun/Oracle decided to implement var-args in Java 5 and has turned out to be a pretty handy feature. Unfortunately, C++ doesn't support this syntax afaik.
Upvotes: 0
Reputation: 78953
Since you also tagged with C: in C you can use a macro combined with a so-called compound literal
#define FUNCTION(ARGC, ...) (Function((ARGC), (unsigned short[]){ __VA_ARGS__ }))
This is type safer that the acient va_list
functions, since it converts all the expressions in the list to unsigned short
.
Modern C++ now also has this VA_ARGS
feature for the macro preprocessing phase. But I don't know how you would create a vector as a temporary that would be initialized with the values.
Upvotes: 3
Reputation: 622
To write a function like that in C, you need to va_list and other macros. This stems from the conversion from C to assembly. In assembly, you can just "look up" on the stack frame to look at what may be more arguments passed to the function.
However, in C, the way this must be done using the va_list types and macros because there is no other built-in mechanism you could use while still maintaining the function's prototype (the number and types of arguments).
Refer to http://www.gnu.org/software/libc/manual/html_node/Variadic-Functions.html.
Upvotes: 1
Reputation: 3346
Make use of default parameters.
Function(int argc, unsigned short *args[], int a = 2, int b = 3, int c = 4) ;
or whatever types you want for yourself. The default values, as are the last three in this example need not be passed to the function. You can call the function like this..
Function (argc, args, 5, 4, 3) ; //have to remember the maximum no. of parameters
I don't know why you want to do this kind of thing in your program. If you do not need the extra variables, why include them in your program? But
Upvotes: 2