I need a way to partially expand a parameter pack. The size of the subset has to be determined by another variadic parameter. It will be more clear what I mean with sample code.
struct EntityA {
EntityA(int, char, unsigned) {}
EntityA(int, char, unsigned*) {}
EntityA(int, char*, unsigned*) {}
EntityA(int*, char*, unsigned*) {}
}
// various types of entities
// ...
// Service provides Args.
template <typename ... Args>
struct Service {
// returns provided Args
template <typename T>
T get() { return T{}; }
};
// this function should call appropriate overload of E by looking at sizeof...(pArgs)
template <typename E, typename ... SArgs>
E
construct(Service<SArgs ...>& service, auto&& ... pArgs) {
// somehow i need to expand and get first half from service and get others from parameters
return E{service.get<SArgs> ..., std::forward<decltype(pArgs)>(pArgs) ...};
}
int main() {
Service<int, char, unsigned> service;
construct<EntityA>(service);
construct<EntityA>(service, (unsigned*)nullptr);
construct<EntityA>(service, (char*)nullptr, (unsigned*)nullptr);
construct<EntityA>(service, (int*)nullptr, (char*)nullptr, (unsigned*)nullptr);
return 0;
}
Some objects(template parameter E) need to be constructed with parameters partially from service and partially from client code. Is there a way to implement this?
CodePudding user response:
you can use std::index_sequence
for that
template <typename E, typename ... SArgs, typename ... PArgs>
E construct(Service<SArgs...>& service, PArgs&& ... pargs) {
constexpr auto size = sizeof...(PArgs);
constexpr auto missing_size = 3 - size; // note: you need to somehow know the parameter count
using default_types = std::tuple<SArgs...>;
return [&]<std::size_t ...I>(std::index_sequence<I...>){
return E{
service.template get<std::tuple_element_t<I,default_types>>()...,
std::forward<PArgs>(pargs)...
};
}(std::make_index_sequence<missing_size>());
}