سؤال

I have a tricky question about C++(11) template classes and their instantiation with types determined at runtime:

Following scenario: The user defines the type of a template class using a config file (ROS parameters). This determines only the type of the template class, not the further logic:

Class definition:

template<typename T>
class MyClass {
    //[...]
}

Exemplary code:

/* [Read parameter and write result to bool use_int] */

std::unique_ptr<MyClass> myclassptr {nullptr};
if(use_int) {
    myclassptr.reset(MyClass<int>);
} else {
    myclassptr.reset(MyClass<double>);
}

myclassptr->foobar();

/* [more code making use of myclassptr] */

So this code is (of course) not compiling, because the unique_ptr template must be specified also with the template type. However, then the problem arises that the template type must be the same for all objects assigned using reset.

One ugly solution would be to copy the code myclassptr->foobar(); and the following into each branch of if/else, which I really don't like.

I would like to see a solution similar to this:

/* [Read parameter and write result to bool use_int] */

MyClass<use_int ? int : double> myclass;
myclass.foobar();

What I have read so far is that something like this is also not possible.

Does anybody have a nice solution for this?

هل كانت مفيدة؟

المحلول

The simplest way to do this is:

class IClass{
  virtual ~IClass {}
  virtual void foobar()=0;
};
template<typename T>
class MyClass:public IClass {
public:
  void foobar() override {
    // code here
  }
};
std::unique_ptr<IClass> myclassptr {};
if(use_int) {
  myclassptr.reset(new MyClass<int>());
} else {
  myclassptr.reset(new MyClass<double>());
}
myclassptr->foobar();

boost::variant would be another solution, but is usually used for unrelated types. Type erasure could be done, but again that is usually done when you have unrelated types you want to impose a uniform interface on.

In other languages generics look sort of like templates, but are actually an abstract interface with auto-generated typecasting and some typechecking added. C++ templates are function or class compile time factories. Two outputs of such factories are unrelated at runtime by default, and you can add such relations if you want.

نصائح أخرى

Depending on what you want, you can make MyClass a variant type that holds either an int or a double, or you could use type erasure to hide the implementation behind an interface. The Boost.Variant library can help to implement the former.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top