I need to pass from a minumum fo one to a maximum of seven file paths to a function. There is a convention where the file path alone is enough to identify how to handle each file.
Order of the parameters does not matter.
An obvious option to handle this (the one I currently implemented) is to pass an empty string as a parameter for unused slots.
Another one is to pass the parameters as an array or vector.
Yet another one would be to implement all possible permutations of parameters (possible, not practical).
I wonder if there is a way to simply specify that the number of paramters can vary, and then simply pass the parameters themselves.
So for example assuming that there is only one implementation of f() with special syntax to denote varying amounts of parameters
All fo the following should compile:
int main()
{
f(file);
f(file1, file2);
f(file1, file3, file2, file6);
}
Is there a way to achieve this in C++ ?
You can use a recursive template function.
#include <iostream>
template <typename First>
void f(First&& first) {
std::cout << first << std::endl;
}
template <typename First, typename... Rest>
void f(First&& first, Rest&&... rest) {
f(std::forward<First>(first));
f(std::forward<Rest>(rest)...);
}
int main() {
f(6,7,8,9,10);
}
If you really need a variable (unbounded) number of arguments:
If you are on C++11 or later:
Use std::initializer_list (only if all the types are the same) -- see https://stackoverflow.com/a/16338804/9305398.
Use variadic templates (i.e. parameter packs) -- see @super's answer and/or https://stackoverflow.com/a/16338804/9305398.
If you are on C++03 or later:
Otherwise, if you have a fixed number of (optional) parameters:
If you are on C++20 or later:
If you are on C++03 or later:
Use a nullable/optional type (e.g. a raw pointer, boost::optional, C++17's std::optional...) -- see @NicolBolas' answer.
Define all required/logical overloads (possibly using custom types) -- ugly, but this may be automated via an external code generator and/or with the preprocessor.
Otherwise, if you can use a different design to accomplish the same thing, you can do any of the following -- for C++03 and later:
Pass a pointer to a struct as suggested by @PaulMcKenzie.
Design a class that allows to set properties (through the constructor and/or methods) and then has member functions to perform operations on that data, e.g.:
ShaderCompiler sc(vs, fs, ...);
sc.setGeometryShader(...);
sc.compile();
A particular nice way (see e.g. QString) is to design a class that allows to do:
result = ShaderCompiler()
.vertex(...)
.fragment(...)
...
.compile()
;
Similarly, exploiting argument-dependent lookup:
Shader()
<< Vertex(...)
<< Fragment(...)
...
;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With