I need to refactor the following code (simplified for clarity) :
#include <iostream> // those structs cannot be changed struct Foo1 {int f;}; struct Foo2 {int g;}; struct Foo3 {int h;}; void processFoo(Foo1 &foo) { } void processFoo(Foo2 &foo) { } void processFoo(Foo3 &foo) { } bool selectFoo2() { // known at run time return true; } bool selectFoo3() { // known at run time return false; } template<typename ...FooT> void save(const FooT &...foos) { std::cout << "foos = " << sizeof...(foos) << std::endl; } void handle_foos() { // Foo1 is always selected Foo1 f1; processFoo(f1); if (selectFoo2()) { Foo2 f2; processFoo(f2); if (selectFoo3()) { Foo3 f3; processFoo(f3); save(f1, f2, f3); } else save(f1, f2); } else if (selectFoo3()) { Foo3 f3; processFoo(f3); save(f1, f3); } else save(f1); } int main(int, char**) { handle_foos(); return 0; } The handle_foos function works as expected with only selected types being passed as arguments to the variadic save function.
However, the code will eventually become less readable with new types (not so many types though) and all those nested if for all combinations of types in the save call.
It is not possible to change the structs definition and the save function.
Basically, i would like to have only one call the the save function with arguments being selected types only. I am looking for a C++14 solution.
I am thinking about storing types that are always selected (known at compile time) in a std::tuple and then using std::tuple_cat to dynamically add selected types at runtime. Then convert the tuple into a parameter pack and pass it to the save function.
I am not sure it's a good idea, is there something more elegant or efficient ?
Thank you.
c++tag because the base language tag should always be added.std::forward.tuple_catmethod I think must fail – each kind of tuple is still its own type, and hence a compile time thing. If you want to register types at run time, you will need a runtime variable container, not a tuple. Which means that your type information must be stored as explicit member of the variant type you're building. Paramter pack unpacking is still a compile-time thing!savetake pointers rather than references. Teach it to skip nulls. Thenhandle_foosbecomes straightforward.std::applyyourself in C++14), it will probably generate around 1 MB worth of code before you reach 10 types