Acorn
Acorn

Reputation: 1165

Shared_Ptr<Derived> being upcast to Shared_Ptr<Base>

I am trying to attach bits of data, called components, to an Entity node. However, whenever I attach a derived component type to the Entity node, it is being upcasted to the base Component type instead of staying a child. How could I prevent this so I can make use of std::type_index? Currently, because the Component is being upcasted, std::type_index keeps making an index for Component, rather than one of the child classes. Do I have to template out the AttachComponent method? I'd rather not.

class Entity final
    {
        //Typedefs
        typedef std::map<std::type_index, std::shared_ptr<acorn::Component> > ComponentMap;


        ComponentMap m_components;
        unsigned long int m_ID;

    private:


    public:
        explicit Entity(unsigned long int id);
        ~Entity();

        //Getters
        inline unsigned long int GetID() const
        {
            return m_ID;
        }

        template<class ComponentType>
        std::weak_ptr<ComponentType> GetComponent()
        {

            auto component_map_it = m_components.find(std::type_index(typeid(ComponentType)));
            //If the component was found
            if (component_map_it != m_components.end()) {
                //Get the shared_ptr of the component
                std::shared_ptr<acorn::Component> base_ptr = component_map_it->second;
                //Cast it to the desired component type
                std::shared_ptr<ComponentType> converted_ptr(std::static_pointer_cast<ComponentType>(base_ptr));
                //Convert to a weak pointer
                std::weak_ptr<ComponentType> return_ptr(converted_ptr);

                //Return the weak pointer
                return return_ptr;
            } 
            else {
                //If no component type was found, return a nullptr.
                return  std::weak_ptr<ComponentType>();
            }

        }

        //Setters
        inline void AttachComponent(std::shared_ptr<Component> component)
        {
            auto raw_ptr = component.get();
            auto insert_pair = std::make_pair(std::type_index(typeid(raw_ptr)), component);
            m_components.insert(insert_pair);
        }

    };`

Upvotes: 1

Views: 226

Answers (1)

Yes, you have to make AttachComponent a template. That's the only way to preserve the type information:

template <class T>
void AttachComponent(std::shared_ptr<T> component)
{
  // as before
}

Upvotes: 1

Related Questions