Intro
This is an old question but things have improved (slightly) in C++ since it was first asked and it may benefit from a fresh look.
Background
I'm thinking of the zpp::bits
library and the "Killing C++ Serialization Overhead & Complexity - Eyal Zedaka - CppCon 2022" talk that its author gave at CppCon 2022.
What this library does is that it uses the structured bindings (c++17) in order to unpack classes members automagically, and it uses template magic to detect exactly how many members the class has. This process is not pretty as structured bindings don't support the variadic syntax yet, so it relies on the old trick of manually trying for case of 1 member, then 2, then 3, etc. This limits this library to 50 member classes for the moment. See this line for what I mean.
There are other limitations, like when dealing with private members, but for those I will refer you to the library's docs as in this specific case we have a simple struct with all public members.
So I'm thinking that for this problem you could use the same mechanism zpp::bits
uses to unpack the class and then inject it into a variadic template function's argument list...
From what I've seen so far you could use the visit_members()
function to do exactly what you need like this code in the library does.
This same solution could apply to this other SO question. Equally, the AggregatesToTuples library used in that question could be used here, but I prefer the zpp::bits
approach.
Working example with zpp::bits
#include <iostream>
#include <https://raw.githubusercontent.com/eyalz800/zpp_bits/main/zpp_bits.h>
// Example types that can be passed in
struct Ctx1 {
int i = 1;
};
struct Ctx2 {
std::string s = "string";
double d = 6.28;
};
// The test function OP requested to be called
template <typename... CtxItems>
auto TestFunc(CtxItems&&... ctx_items) -> void {
std::cout << "TestFunc called with " << sizeof...(ctx_items) << " args:" << std::endl;
((std::cout << " - arg: " << ctx_items << std::endl), ...); // print the args
}
int main() {
Ctx1 ctx1;
zpp::bits::access::visit_members(ctx1, [](auto &&... items) constexpr {
return TestFunc(items...);
});
Ctx2 ctx2;
zpp::bits::access::visit_members(ctx2, [](auto &&... items) constexpr {
return TestFunc(items...);
});
return 0;
}
Godbolt Demo
Output:
Program returned: 0
TestFunc called with 1 args:
- arg: 1
TestFunc called with 2 args:
- arg: string
- arg: 6.28
Future
Should the "Structured Bindings can introduce a Pack (P1061R2)" paper land, this code would become a lot simpler and we could probably implement something directly as opposed to relying on the internals of zpp::bits
.