is there any easy way to acheive the conveniece of passing arguments not in a specific order without repetative overloading?
Yes, you can do this, but because you haven't said what is your exact usage of this function I am not able to give you general purpose solution to this. Anyway, for all people claiming in the comments that behavior which is needed by the author of the question is wrong, bad, stupid etc, please consider following piece of code, which works and I see potential in this.
Let's assume that we have a class which has fields which store some values and we want to have a setters (and probably getters as well) to access those values (for the clarity I presented only minimum version).
So, this class would be:
struct A {
int g1 {};
int g2 {};
int g3 {};
};
This class does not have setters or getters because we are going to wrap it in different class, a Data class.
struct Data {
template <typename... Ts>
void set (Ts&&... ts) {
set_impl (std::forward<Ts> (ts)...);
}
A a;
private:
template <typename T>
void set_impl (T&& t) {
a.*T::mem = t.v; // (X)
}
template <typename T, typename K, typename... Ts>
void set_impl (T&& t, K&& k, Ts&&... ts) {
set_impl (std::forward<T> (t));
set_impl (std::forward<K> (k), std::forward<Ts> (ts)...);
}
};
So here we have a class which has set member function which takes arbitrary number or arguments and each of them can be (and in this example should be) of different type. To set A fields like you see in (X) you need to pass an object of type which has a pointer to A member. So please take a look at the following classes.
struct G {
G (int c = {}) : v {c} {}
int v;
};
struct G1 : G { using G::G; static constexpr int A::* mem = &A::g1; };
struct G2 : G { using G::G; static constexpr int A::* mem = &A::g2; };
struct G3 : G { using G::G; static constexpr int A::* mem = &A::g3; };
All Gx functions are here only for setting the value of A fields and each of them knows which field is going to set.
Helper function for showing the result is:
void show (const A& v) {
std::cout << "g1 = " << v.g1 << std::endl;
std::cout << "g2 = " << v.g2 << std::endl;
std::cout << "g3 = " << v.g3 << std::endl;
}
And finally, the usage:
Data d;
d.set (G1 {10}, G2 {20}, G3 {30});
show (d.a);
Data p;
p.set (G3 {40}, G1 {-30}, G2 {120});
show (p.a);
which gives us the output:
g1 = 10
g2 = 20
g3 = 30
g1 = -30
g2 = 120
g3 = 40
Like I said, I do not know if this fits your needs, but this is just an example how to do this and it maybe helpful for you.
Nonetheless putting values in not specified order (in conjunction with arbitrary number of values) has advantage that you can set only those values that are needed.