I would like to have a function that accepts a std::map
containing a (pointer to a) base class, but I can't get it to work. Here is my minimal and simplified example:
struct Entity {
int i;
Entity(const int i_) : i(i_) {}
virtual ~Entity() {}
};
struct A : public Entity {
bool a;
A(const int i_, const bool a_) : Entity(i_), a(a_) {}
};
void efunc(const std::map<int, std::shared_ptr<Entity>>& m) {
for (auto& it : m) {
std::cout << it.second->i << std::endl;
}
}
int main() {
std::map<int, std::shared_ptr<A>> aMap;
std::shared_ptr<A> myA = std::make_shared<A>(1, true);
aMap.insert({myA->i, myA});
// efunc(aMap); // DOES NOT WORK
}
Obviously simply passing the map
this way is not allowed, but how can I make it work?
As a bonus, how would I detect the type in the map so that I can execute code specific to that subclass?
Thank you in advance!
Update: Using templates seems to do the trick, this is what I'm using right now:
template <class T>
void tfunc(const std::map<int, std::shared_ptr<T>>& m) {
for (auto& it : m) {
std::cout << it.second->i << std::endl;
}
}
It does feel a bit strange, since I loose IntelliSense and I don't understand why the compiler is not giving me an error. I feel like concept
s might help (e.g. to make sure T
inherits Entity
), but this is beyond what I need right now.
Thank you again for all the responses!
Update 2: Alright, here it is using concepts to ensure that the template
containst the member i
:
template <class T>
concept hasI = requires(T a) { a.i; };
template <class T>
concept inheritsEntity = std::derived_from<T, Entity>;
template <hasI T>
/// alternative: template<inheritsEntity T>
void tfunc(const std::map<int, std::shared_ptr<T>>& m) {
for (auto& it : m) {
std::cout << it.second->i << std::endl;
}
}