I’m trying to generate input for a function whose signature is defined with a variadic template. Depending on the index of the parameter, I need to return different values. The closest solution I could find was the second solution listed here by Julius. It uses an initialization list to force execution order, which solves the original problem by incrementing an index each time one of the arguments is generated. However it fails when the return type of the main function (in this case, print7) is void because it relies on caching the return value as a variable. I’ve included a simplified version of the solution below for reference.
#include <iostream>
int pos = 0;// DEBUG: observe the order of `GETPARAM` calls
template<typename T>T GETPARAM();
template<>
int GETPARAM() { return 100 + pos++; }
template<>
double GETPARAM() { return 100.5 + pos++; }
template<>
const char* GETPARAM() { pos++; return "hello"; }
////////////////////////////////////////////////////////////////////////////////
template<class Ret>
struct ArgEvalOrderer {
Ret ret;
template<class... Args>
ArgEvalOrderer(
Ret(*f)(Args...),
Args... args
)
: ret{f(args...)}
{}
operator Ret() const { return ret; }
};
template<class Ret, class... Args>
Ret call_after_ordered_argfetch(Ret(*f)(Args...)) {
// evaluation order guaranteed by braced init list
return ArgEvalOrderer<Ret>{f, GETPARAM<Args>()...};
}
int print3(int a, int b, double c) {
std::cout << "print7: " << a << ", " << b << ", " << c << std::endl;
return 1;
}
int main() {
call_after_ordered_argfetch(print7);
return 0;
}
The author of the answer said there was no problem with the void return type, but if I modify the return type of print3 above to be void, compilation fails.
To add an additional layer of complexity here, I’m avoiding the use of the std library.
Any solutions, whether iterating on the above solution or in an entirely different direction, would be greatly appreciated.