Example: rtti_example1ΒΆ

Example console output:

Part 1:

RTTI Foo (static): Foo
class: Bar
class: Bar
Is Foo?     => No
Is BarBase? => Yes
Is Bar?     => Yes
specificBarMethod: reached.

Part 2:

Known class: Bar, children of BarBase
Known class: BarBase, children of CObject
Known class: CObject, children of (none)
Known class: Foo, children of CObject
Known class: Bar, children of BarBase
specificBarMethod: reached.

C++ example source code:

/* +------------------------------------------------------------------------+
   |                     Mobile Robot Programming Toolkit (MRPT)            |
   |                          https://www.mrpt.org/                         |
   |                                                                        |
   | Copyright (c) 2005-2021, Individual contributors, see AUTHORS file     |
   | See: https://www.mrpt.org/Authors - All rights reserved.               |
   | Released under BSD License. See: https://www.mrpt.org/License          |
   +------------------------------------------------------------------------+ */
#include <mrpt/rtti/CObject.h>

#include <iostream>
#include <memory>

namespace MyNS
{
class Foo : public mrpt::rtti::CObject
{
   public:
    Foo() {}
    DEFINE_MRPT_OBJECT(Foo, MyNS)

    void printName() { std::cout << "printName: Foo" << std::endl; }
};

class BarBase : public mrpt::rtti::CObject
{
   public:
    BarBase() {}
    DEFINE_VIRTUAL_MRPT_OBJECT(BarBase)

    virtual void printName() { std::cout << "printName: BarBase" << std::endl; }
};

class Bar : public BarBase
{
   public:
    Bar() {}
    DEFINE_MRPT_OBJECT(Bar, MyNS)

    void printName() override { std::cout << "class: Bar" << std::endl; }
    void specificBarMethod()
    {
        std::cout << "specificBarMethod: reached." << std::endl;
    }
};
}  // namespace MyNS

IMPLEMENTS_MRPT_OBJECT(Foo, mrpt::rtti::CObject, MyNS)
IMPLEMENTS_VIRTUAL_MRPT_OBJECT(BarBase, mrpt::rtti::CObject, MyNS)
IMPLEMENTS_MRPT_OBJECT(Bar, MyNS::BarBase, MyNS)


void Test_UserTypes()
{
    using namespace MyNS;
    const auto id_foo = CLASS_ID(Foo);
    std::cout << "RTTI Foo (static): " << id_foo->className << std::endl;

    // Pointers:
    Bar::Ptr pBar = std::make_shared<Bar>();
    BarBase::Ptr pBase = mrpt::ptr_cast<BarBase>::from(pBar);
    mrpt::rtti::CObject::Ptr pObj =
        mrpt::ptr_cast<mrpt::rtti::CObject>::from(pBar);

    pBar->printName();
    pBase->printName();
    std::cout << "Is Foo?   => " << (IS_DERIVED(*pObj, Foo) ? "Yes\n" : "No\n");
    std::cout << "Is BarBase? => "
              << (IS_DERIVED(*pObj, BarBase) ? "Yes\n" : "No\n");
    std::cout << "Is Bar?  => " << (IS_DERIVED(*pObj, Bar) ? "Yes\n" : "No\n");
    if (IS_CLASS(*pObj, Bar))
    {
        auto pBar2 = mrpt::ptr_cast<Bar>::from(pObj);
        pBar2->specificBarMethod();
    }
}


void do_register()
{
    // Register with explicit namespace:
    mrpt::rtti::registerClass(CLASS_ID_NAMESPACE(Foo, MyNS));
    {
        // Register without explicit namespace:
        using namespace MyNS;
        mrpt::rtti::registerClass(CLASS_ID(BarBase));
        mrpt::rtti::registerClass(CLASS_ID(Bar));
        mrpt::rtti::registerClassCustomName("MyNS::Bar", CLASS_ID(Bar));
    }
}

void Test_UserTypesFactory()
{
    do_register();

    // Test register:
    {
        const auto& allClasses = mrpt::rtti::getAllRegisteredClasses();
        for (const auto& cl : allClasses)
        {
            std::cout << "Known class: " << cl->className << ", children of "
                      << (cl->getBaseClass ? cl->getBaseClass()->className
                                           : "(none)")
                      << std::endl;
        }
    }

    // Test factory:
    {
        mrpt::rtti::CObject::Ptr pObj = mrpt::rtti::classFactory("MyNS::Bar");
        if (IS_CLASS(*pObj, MyNS::Bar))
        {
            auto pBar = mrpt::ptr_cast<MyNS::Bar>::from(pObj);
            pBar->specificBarMethod();
        }
    }
}


int main(int argc, char** argv)
{
    try
    {
        Test_UserTypes();
        Test_UserTypesFactory();
        return 0;
    }
    catch (const std::exception& e)
    {
        std::cerr << "MRPT error: " << mrpt::exception_to_str(e) << std::endl;
        return -1;
    }
}