0

Consider the following code:

class Base {
  virtual bool someFunc() = 0;
  virtual ~Base() = default;
};


class Derived1 : public Base {
  bool someFunc() override { ... }
};


class Derived2 : public Base {
  bool someFunc() override { ... }
};


class MyClass {
public:
  MyClass(std::vector<Base> derivedClasses) {
    for (const auto dClass : derivedClasses) {
      m_derivedClasses.emplace_back(std::make_shared<???>(dClass));
    }
  }

  std::vector<std::shared_ptr<Base>> m_derivedClasses;
};


int main() {
  std::vector<Base> listOfDerivedClasses = {Derived1(), Derived2()};
  MyClass mClass(listOfDerivedClasses)
  
  for (const auto dClass : m_derivedClasses) {
    dClass.someFunc();
  }
}

Essentially, I have a class that is given a list of derived classes in its constructor, and I want to convert it to a list of pointers to those derived classes so that I can execute the appropriate someFunc() function in main(). I can't seem to figure out how to get this working, do I need some template magic?

EDIT: I could make the MyClass constructor take a std::vector<Base*> and likely get things to work like that, but it requires the consumer to create the pointers themselves and I'm hoping to shield them from that. In another class I worked on, where I wanted polymorphic behavior, I was able to achieve something like this using templates:

template <typename derivedTypeT, std::enable_if_t<std::is_base_of_v<Base, derivedTypeT>, bool> = true>
MyOtherClass(const derivedTypeT &dClass) : m_dClass(std::make_shared<derivedTypeT>(dClass)) {}

I don't know how I can make this work if the input is a std::vector though, since it obviously could have multiple derived types. Is this something I could do with variadic templates?

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
rmsantos
  • 105
  • 6
  • 1
    `std::vector` [sliced away](https://stackoverflow.com/questions/274626/what-is-object-slicing) all of the derived-ness. You have to start with pointers and polymorphism from the beginning to get what you want. – user4581301 Jul 17 '20 at 19:25
  • I understand I can make the constructor take a list of pointers and store that in my list. That would require the user to create the polymorphic pointers themselves and I'm hoping to shield them from that. Sounds like that may not be possible? – rmsantos Jul 17 '20 at 19:25
  • 1
    I don't think you can protect them here without getting really tricky with [a parameter pack](https://en.cppreference.com/w/cpp/language/parameter_pack) or similar template voodoo, but `vector` is not the tool to use here. Perhaps `unique_ptr`-returning static factory functions in the derived classes? – user4581301 Jul 17 '20 at 19:30
  • 1
    @rmsantos "*That would require the user to create the polymorphic pointers themselves and I'm hoping to shield them from that*" - but, you are already doing that in your `main()` anyway. You are trying to create a vector of objects (which doesn't work due to slicing), so why not a vector of pointers instead (or at least a vector of `reference_wrapper`s)? What are you really trying to shield here? The user decides which classes to create objects of anyway, so let them create those objects in a way that is compatible with passing around polymorphic types. – Remy Lebeau Jul 17 '20 at 20:43

0 Answers0