Skip to content

Allow passing a derived object to a port requiring a base class #943

Closed

Description

@captain-yoshi

Is your feature request related to a problem? Please describe.
There is a lot of boilerplate code needed for converting libraries, relying on inheritance, into BT nodes. Consider this example:

// Base class
class Greeter {
 public:
  virtual std::string show_msg() const = 0;
  virtual ~Greeter() {}
};

// Derived class
class HelloGreeter : public Greeter {
 public:
  std::string show_msg() const override { return "hello"; }
  void setDerivedParameter(int n);
};

I have 2 options if I want to use a unique method from the derived class as well as store it's base class somewhere, e.g. inside a vector.

<!-- OPTION 1- return base and derived class -->
<CreateHelloGreeter out_derived="{hello_greeter}" out_base="{greeter}" />

<!-- OPTION 2- convert to base -->
<CreateHelloGreeter out_derived="{hello_greeter}" />
<UpcastHelloGreeter in={hello_greater} out_base="{greeter}" />

<setDerivedParameter in_derived="{hello_greater}" n="2" />
<VectorInsertGreeter in_base="{greeter}" />

Describe the solution you'd like
I would like the ability to allow passing a derived object directly to a port requiring a base class.

<CreateHelloGreeter out_derived="{hello_greeter}" />

<setDerivedParameter in_derived="{hello_greater}" n="2" />
<InsertToGreeterVector in_base="{hello_greeter}" />

As you see, this would reduce boilerplate code in the C++ and in the XML representation. Is there any way to reduce the strictness of the custom std::any used in this project to enable this feature ? I think that this project https://github.com/samee/any_of implements this behavior.

There is also the problem that BT evaluates ports type for consistency. I don't think one can deduce the base class of a derived class
typeid...

Activity

  1. facontidavide commented on Mar 1, 2025

    @facontidavide
    Collaborator

    this is a good point.

    Yes, I think it is safe to reduce the strictness of the any_cast.

    Can you please help creating a PR with a unit test of the desired behavior, i.e. somehting like this should work out of the box

    <CreateHelloGreeter out_derived="{hello_greeter}" />
    <setDerivedParameter in_derived="{hello_greater}" n="2" />
    <ShowGreetMessage in_base="{hello_greeter}" />

    There is also the problem that BT evaluates ports type for consistency. I don't think one can deduce the base class of a derived class typeid...

    I am not sure if there is an easy fix for that, I need to investigate

  2. self-assigned this
    on Mar 1, 2025
  3. facontidavide commented on Oct 24, 2026

    @facontidavide
    Collaborator

    Fixed by #1107 (1e166f5). Register the inheritance once with factory.registerPolymorphicCast<Derived, Base>(), and a std::shared_ptr<Derived> output can then be read by a std::shared_ptr<Base> input port (see tests/gtest_polymorphic_ports.cpp). Making the cast automatic, without registration, would need a separate feature request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions