0

Let's say I have three very different classes with no common parent: Camera, Light, Model. But all three have the same generic SetPos(float x, float y, float z) method that translates their position in 3D space. I also have a reference list (e.g. std::map) that stores pointers to objects of all three classes of type void* - meaning it's generic and non-descript.

So to summarize: I have a bunch of cameras, lights and models with very different data structures that all can be moved around using SetPos method that each have and I keep generic, no-type void* pointers to all of them in a single map for quick access.

What I want to know is if it's possible to somehow call that SetPos from a void* without determining class object type (e.g. storing it in that std::map and then casting that void* to a proper class pointer using it)?

Is there some template idea for it?

Or should I just create a generic interface class that will have a pure virtual method SetPos(x,y,z) and simply make those three classes inherit from it - and be done with it by simply casting that pointer to that single class - but I'd rather avoid this option because... reasons and what if some alternative way is better?

krz
  • 11
  • 3
  • You will need some way to know what to cast the `void*` to. For example, instead of a map of `void*`, use a map of `std::pair`. – Raymond Chen Jul 02 '22 at 20:59
  • 3
    You should almost never use `void*` , use `std::variant` with its `std::visit` to dispatch the call. – Quimby Jul 02 '22 at 21:00
  • No, without determining the type this is 100% impossible in general: You need to determine the logic used to modify data of the object which is probably different for the types. If you use the logic of the wrong type you end up with undefined behaviour. – fabian Jul 02 '22 at 21:01
  • *"very different data structures"* -- so how is a single function supposed to know where to find the position that needs to be adjusted? – JaMiT Jul 02 '22 at 21:03
  • Either variant, or - in the unlikely case when it's all AggregateTypes, you might have e.g. the first member as type (which is essentially variant reimplemented). – lorro Jul 02 '22 at 21:04
  • Does this answer your question? [Map a void\* back to its original type](https://stackoverflow.com/questions/20720610/map-a-void-back-to-its-original-type) – Raymond Chen Jul 02 '22 at 21:06

1 Answers1

1

Yes there is a template for this, use std::variant instead of void*. I guess your code contains some dynamic casts or worse already to interact with the stored objects. That is bad design in general, type system is our friend, types should not be erased lightly.

Then you can do something akin to this:

std::variant<A,B,C> obj;
...
std::visit(obj,[&](auto& o){o.SetPos(x,y,z);};
Quimby
  • 17,735
  • 4
  • 35
  • 55