I'm writing C++ class that interfaces with a library. The library has a bunch of functions that look like the following:
Library.h
int FunctionA(int deviceNumber, ...);
int FunctionB(int deviceNumber, ...);
int FunctionC(int deviceNumber, ...);
int FunctionD(int deviceNumber, ...);
int FunctionE(int deviceNumber, ...);
Each instance of my C++ class has an associated deviceNumber which never changes, so I have deviceNumber stored as a member variable, and every time I call a library function, I pass the member in as the function call's first argument.
This is fine, and there's no real reason for me to change the way it is. But out of curiosity, I was wondering if C++ had any mechanism to "transform" arguments that would let me avoid passing the same argument in every call. The obvious way to accomplish this is to overload everything. Let's say my class is called Foo:
Foo.cpp
int Foo::FunctionA(...) {
// deviceNumber_ is a const member
return ::FunctionA(deviceNumber_, ...);
}
The only problem is that this requires a method for each function call, so as the library grows, it gets more and more annoying without a code generator.
Is there any general way to provide the overloading behaviour without actually overloading the functions? Is there a mechanism in C++ to "expand" an argument into multiple arguments? I'm imagining it would look like:
// These two calls are equivalent
FunctionA(deviceNumber, ...);
FunctionA(Magic(...));
// Magic() expands the arguments, adding deviceNumber
Even if the solution is much uglier and less readable than leaving everything alone, I'm curious if it's possible. After searching around, variadic templates seem to be the closest match, but I can't really wrap my head around how they could be used to accomplish this.
You might be happy with a generic relay function:
Live On Coliru
#include <iostream>
int foo1(int device_number, const char*) { std::cout << __PRETTY_FUNCTION__ << "\n"; return device_number*42; }
double foo2(int device_number) { std::cout << __PRETTY_FUNCTION__ << "\n"; return device_number*3.14159; }
struct facade {
facade(int dn) : device_number(dn) {}
template <typename F, typename... A>
auto call(F&& f, A&&... args) const {
return std::forward<F>(f)(device_number, std::forward<A>(args)...);
}
private:
int device_number;
};
int main() {
facade dev(2);
std::cout << dev.call(foo1, "yes ma'am") << "\n";
std::cout << dev.call(foo2) << "\n";
}
I would probably choose a marco in the cpp file as the easiest solution (strictly in the cpp file though)
Variadic templates could help here too. However it sounds like you are doing something embedded and that might be an issue.
Also, I'm not sure if you mean that each FunctionA is overloaded or FunctionA refers to exactly one function.
Anyway, my template solution will help if there are multiple FunctionAs
template<typename... Args>
int Foo::FunctionA(Args&& ...args) {
return ::FunctionA(deviceNumber_, std::forward<Args>(args)...);
}
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