I am writing a wrapper for some client-server function calls, and I need a way to set some output parameter before or after the actual call. Sample code follows:
#include <iostream>
#include <functional>
#include <string>
#include <vector>
void tryp(int a, int b, int &c, std::vector<char> ghost) { c = 7; }
void AssignRefs() {
std::cout << "P2" << std::endl;
}
template <typename T>
void IsolateRef(T &&t) {
t = 99;
}
template<typename T, typename ... A>
void AssignRefs(T &&t, A && ... a) {
IsolateRef(t);
std::cout << "P1" << std::endl;
AssignRefs(a ...);
}
template<typename ... A>
std::function<void(A ...)> wrap(void (*fn)(A ...)) {
return [](A ... a) { AssignRefs(a ...); };
}
int main() {
int z = 6;
int y = 4;
int a = 9;
int b = 77;
tryp(1,4,y,std::vector<char>{'H'});
wrap(tryp)(1,2,z,std::vector<char>{'Z'});
std::cout << "Results here: " << y << " :: " << z << " :: " << a << " :: " << b << std::endl;
}
This of course does not compile. See Try it online! link for more information. It would work if I deleted the line "t = 99"
.
What I really need is a template specialization for AssignRefs
or IsolateRef
to skip over non-reference parameters.
The issue now is that if I omit the '&&'
before the type in the function definition, all parameters would lose their reference qualifier, and the call to IsolateRef
would not do anything. But with the '&&'
every parameter is passed by reference to the function IsolateRef
.
I want two separate functions, one to operate on non-const reference types and the other to skip over the rest of the parameters.
Is there any simple way to implement it in the above code?
Thanks a lot.
From your code, you might use std::forward
and replace IsolateRef(T &&t)
by 2 overloads, one for non-const reference, and one for const reference (No-op)
template <typename T> void IsolateRef(T &t) { t = 99; }
template <typename T> void IsolateRef(const T &) { /*Empty*/ }
template<typename T, typename ... A>
void AssignRefs(T &&t, A && ... a) {
IsolateRef(std::forward<T>(t));
std::cout << "P1" << std::endl;
AssignRefs(std::forward<A>(a) ...);
}
template<typename ... A>
std::function<void(A ...)> wrap(void (*fn)(A ...)) {
return [](A ... a) { AssignRefs(std::forward<A>(a) ...); };
}