If there is a method, which aims to put objects with specific type into another list, how can I use a user-defined parameter in the dynamic_cast
? I know, that I can not use the std::string parameter directly in dynamic_cast
, but is there a better solution?
std::list<Car*> GetCarsOfType(std::string type)
{
std::list<Car*> carsOfType;
for (int i = 0; i < cars.size(); ++i)
{
if (dynamic_cast<type> cars[i]) // This is not possible, but how can I solve this in a better way?
{
carsOfType.push_back(cars[i]);
}
}
return carsOfType;
}
You could keep a central repository of the mapping between the named car type and the actual type if you wish. It could then be used to do the dynamic_cast
test for you.
Example:
#include <algorithm>
#include <unordered_map>
std::list<Car*> GetCarsOfType(std::string type) {
// map between the named type and the dynamic_cast test:
static const std::unordered_map<std::string, Car*(*)(Car*)> cast_checkers{
{"SUV", [](Car* c) -> Car* { return dynamic_cast<SUV*>(c); }},
{"Limo", [](Car* c) -> Car* { return dynamic_cast<Limo*>(c); }}
};
std::list<Car*> carsOfType;
// a filter that only returns true for those you want
auto flt = [&type](Car* c) { return cast_checkers.at(type)(c) != nullptr; };
std::ranges::copy_if(cars, std::back_inserter(carsOfType), flt);
return carsOfType;
}
Or using a view
:
#include <ranges>
#include <unordered_map>
std::list<Car*> GetCarsOfType(std::string type) {
static std::unordered_map<std::string, Car* (*)(Car*)> cast_checkers{
{"SUV", [](Car* c) -> Car* { return dynamic_cast<SUV*>(c); }},
{"Limo", [](Car* c) -> Car* { return dynamic_cast<Limo*>(c); }}};
// same filter as above:
auto flt = [&type](Car* c) { return cast_checkers.at(type)(c) != nullptr; };
// a view over those you want
auto matchview = cars | std::views::filter(flt);
// populate the container using the view:
return {matchview.begin(), matchview.end()};
}