1

I have a list of different types of renderer classes that I have implemented and that I want to store inside of a std::vector<BaseRenderer> and then create a method to retrieve an object based on it's actual class, I have created the following methods for adding and retrieving the objects from said vector.

  // appends a new renderer instance to the vector
  template<typename _tRenderer>
  inline typename std::enable_if<std::is_base_of<BaseRenderer, _tRenderer>::value, void>::type addRenderer(_tRenderer &renderer) {
    renderers_.emplace_back(std::move(renderer));
  }

and the code for retrieving the instance is as follows

  template<typename _tRenderer>
  inline typename std::enable_if<std::is_base_of<BaseRenderer, _tRenderer>::value, _tRenderer>::type getRenderer() {
    auto it = std::find_if(renderers_.begin(), renderers_.end(), [](BaseRenderer &r) -> bool { return dynamic_cast<_tRenderer *>(&r) != nullptr; });
    assert(it != renderers_.end() && "No renderer instance with the requested type was registered in this context");

    return *dynamic_cast<_tRenderer *>(&(*it));
  }

To test this I added a TextRenderer and try to use the latter method to get that same object

context.addRenderer(TextRenderer());
auto tr = context.getRenderer<TextRenderer>();

It fails at the assertion phase as the method couldn't perform dynamic_cast on any of the registered instances, and I couldn't think of a reason for why it is not, other than saving the pointers inside of the vector instead of the full instance which is something that I rather not do.

Some help for pulling this off would be really appreciated as it would be super nice to have such mechanism implemented inside of the library that I'm working on. Thanks in advance.

  • Don't do this. Use pointers. This **will not work** unless all of the objects are exactly the same size, and even then it's extremely risky since that assumption may not hold in the future. – tadman Jul 02 '20 at 14:45

0 Answers0