Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if an instance of base class is one of some derived classes

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.

like image 864
PlsHelp Avatar asked Sep 03 '25 09:09

PlsHelp


1 Answers

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

Live demo

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.

like image 104
wohlstad Avatar answered Sep 04 '25 21:09

wohlstad