I have a class Base
, and it has many derived classes: Derived1
, ...,Derived9
.
Given an instance Base* b
, is there a clean way to check whether b
is an instance of either Derived1
, ...,Derived5
?
The obvious way is to check each one of them:
if (dynamic_cast<Derived1*>(b)) return true;
// ...
if (dynamic_cast<Derived5*>(b)) return true;
return false
This seems unnecessarily repetitive.
Ideally I would like to do something like:
const auto valid_derived_classes = {Derived1,...,Derived5};
for (const auto derived_class : valid_derived_classes)
{
if (dynamic_cast<derived_class*>(b))
{
return true;
}
}
return false;
Is there a way to accomplish something like this?
For context: I want to calculate the temperature of many types of devices, where each device is assigned some sensors. When all the sensors assigned to a device fail, it should measure the temperature according to some emergency sensors. There are few types of devices that should not do this. So when calculating the temperature, I need to check if a device is exceptional.
To answer your immediate question:
Is there a way to accomplish something like this?
You can write a variadic template that uses a fold expression for the dynamic_cast
check:
#include <iostream>
#include <memory>
struct B { virtual ~B() {} };
struct D1 : public B {};
struct D2 : public B {};
struct D3 : public B {};
// Check if pointer to base (B) actually points to one of the derived (Ds):
template <typename... Ds>
bool is_one_of_derived(B* p) {
return (... || dynamic_cast<Ds*>(p));
}
int main() {
std::unique_ptr<B> p1 = std::make_unique<D1>();
// Check if p1 is actually a D1 or D2:
std::cout << std::boolalpha << is_one_of_derived<D1, D2>(p1.get()) << "\n";
std::unique_ptr<B> p3 = std::make_unique<D3>();
// Check if p3 is actually a D1 or D2:
std::cout << std::boolalpha << is_one_of_derived<D1, D2>(p3.get()) << "\n";
}
Output:
true
false
However-
As @Jarod42 commented using dynamic_cast
is usually a code-smell. You should consider an different solution, like using virtual methods.
Reading your comments under the post (and the edit with the context) regarding the sensors, you can simply add a bool
member (with a getter method), that will be set to true
in the base class, and false
in any derived that does not support it.
You can also have a virtual double GetTemperture()
method that polymorphically executes the relevant logic for each device.