jeudi 2 mars 2017

C++ std::shared_pointer with template base class

I am trying to pass a derived class as a std::shared_pointer to a function whose parameter is the base class, which has a template.

Here is a full example:

template <class T>
class Base {
 public:
  std::string typeName()
  {
    int status;
    char *realName = abi::__cxa_demangle(typeid(T).name(), 0, 0, &status);
    std::string ret(realName);

    free(realName);

    return ret;
  }
};

class Derived : public Base<float> {};

The function I would like to call is the 'doSomething' with the shared pointer.

template <class V>
void doSomethingNotShared(Base<V> *test)
{
  std::cout << "Not shared type: " << test->typeName() << std::endl;
};

template <class V>
void doSomething(std::shared_ptr<Base<V>> test)
{
  std::cout << "Shared type: " << test->typeName() << std::endl;
};

And here is the main function to show how I'd like to use it and pointing out the compilation error.

int main()
{

  std::shared_ptr<Derived> testval1 = std::shared_ptr<Derived> (new Derived());
  doSomething(testval1); // <- Compilation error

  Derived *testval2 = new Derived();
  doSomethingNotShared(testval2);

  std::shared_ptr<Base<float>> testCast = std::dynamic_pointer_cast<Base<float>>(testval1); // Would rather not have to do this if there is another way ...
  doSomething(testCast); // <- No error runs fine
}

Is there any way to make this work with doSomething(testval1);? I am hoping to not have to use dynamic_pointer_cast and just use Derived.

The main error is: std::shared_ptr<Derived> is not derived from std::shared_ptr<Base<V> >

I could create a "AnyBase" class that removes the template parameter, but then that would remove some of the type safety that I have in place in my actual application, which is a must.

One thing I'm considering is create a mapping between the new class AnyBase and std::shared_ptr<AnyBase>, then use the function doSomethingNotShared for handling the type safety, and using the lookup mapping to get the shared_ptr. (see below)

std::map<AnyBase *, std::shared_ptr<AnyBase>> 

Aucun commentaire:

Enregistrer un commentaire