Couple of things:
all_components is a type, it does not have size() method. You can use sizeof...(Args) to obtain the length of the pack.
std::get requires a tuple object. Since it is a cast, thus unevaluated context, you can use std::declval<all_components>() to obtain the tuple.
- Because
std::get returns a value, you have to convert it to a type for it to be casted to.
#include <tuple>
#include <functional>
template<typename... Args, typename Action>
void execute(const Action& _action) {
using all_components = std::tuple<Args...>;
auto tuple = std::tie();
for (int s = 0; s < sizeof...(Args); s++) {
tuple = std::tuple_cat(tuple, *reinterpret_cast<decltype(std::get<s>(std::declval<all_components>()))*>(data[s]);
}
std::apply(_action, tuple);
}
But
- you are still missing
data.
- Because
s is used in a template, it has to be constexpr, so the ordinary loop won't compile.
- Is
sizeof of every Arg 1? If not, the deserialization is wrong.
My wild guess is that the data is tightly packed inside the vector. In that case you need something like this:
#include <tuple>
#include <functional>
template<typename...Args>
constexpr auto data_indices(){
std::array is{std::size_t(0), sizeof(Args)...};
for(std::size_t i=1;i<is.size();++i){
is[i]+=is[i-1];
}
return is;
}
template<typename...Args,std::size_t...Is>
auto get_tuple(std::index_sequence<Is...>, const char* data){
auto indices = data_indices<Args...>();
return std::tuple{*reinterpret_cast<const Args*>(data+indices[Is])...};
}
template<typename... Args, typename Action>
void execute(const Action& _action, const char* data) {
std::apply(_action, get_tuple<Args...>(std::make_index_sequence<sizeof...(Args)>{},data));
}
#include <cstring>
#include <iostream>
void foo(int x, double y){
std::cout<<x<<' '<<y<<'\n';
}
int main(){
std::array<char,sizeof(int)+sizeof(double)> arr;
int x = 12;
double y = 24.0;
std::memcpy(arr.data(),&x,sizeof(x));
std::memcpy(arr.data()+sizeof(x), &y,sizeof(y));
execute<int,double>(foo,arr.data());
}
Unless you are using placement new to put the elements into the array, you have to explicitly copy them to the tuple, otherwise you are breaking the strict aliasing rule. So:
template<typename...Args,std::size_t...Is>
auto get_tuple(std::index_sequence<Is...>, const char* data){
auto indices = data_indices<Args...>();
std::tuple<Args...> tuple;
(std::memcpy(&std::get<Is>(tuple), data+indices[Is], sizeof(Args)), ...);
return tuple;
}