mardi 3 janvier 2017

Generic object creation from command line

I have two C++ abstract classes Abs1 and Abs2. Then I have:

`A : public Abs1`
`B : public Abs1` 
`C : public Abs2`
`D : public Abs3`

Now, I'm trying to create objects from command line arguments and I have to do rewrite the public factory function make_abstract in the linked question, something like:

std::unique_ptr<Abs1> makeAbs1 (int argc, const char*argv[])
{

    if (argc == 1) {
        return nullptr;
    }
    const std::string name = argv[1];
    if (name == "A") {
        return detail::make_abstract<A, std::tuple<int, std::string, int>>(argc, argv);
    } else if (name == "B") {
        return detail::make_abstract<B, std::tuple<int, int>>(argc, argv);
    }
}



std::unique_ptr<Abs2> makeAbs2 (int argc, const char*argv[])
{

    if (argc == 1) {
        return nullptr;
    }
    const std::string name = argv[1];
    if (name == "C") {
        return detail::make_abstract<C, std::tuple<int>>(argc, argv);
    } else if (name == "D") {
        return detail::make_abstract<D, std::tuple<int, float>>(argc, argv);
    }
}

As you can see this is terribly redundant. How can I do a generic version of this? In this version we can pass as many implemented class as we want, so the if cascade is not a solution. Notice that we cannot modify any of these classes.

I was thinking that maybe variadic templates could help, but I can't figure out many problems:

template <typename T, typename ...Ts>
std::unique_ptr<T> make (int argc, const char*argv[]){
  const std::string name = argv[1];
  for(Ti : Ts) //this is obviously wrong
    if(typeid(Ts).name == name)
      return detail::make_abstract<T, std::tuple</*Here shoudl be different for every Ti*/>>(argc, argv);

}

Aucun commentaire:

Enregistrer un commentaire