CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 2 of 2
  1. #1
    Join Date
    Aug 2015
    Posts
    1

    Inheritance in template methods

    I need to return a list of T types that are children of ParentPtr (shared_ptr).

    Code:
    std::list<ParentPtr> GetAllParent(ParentPtr pp)
    {
    }

    Code:
    class U:public Parent{}
    std::list<U> ul=GetAllNodes<U>(Shared_ptr_U);
    and my template method that looks like this

    Code:
    template<class T>
    std::list<T> GetAllNodes(std::shared_ptr<T> node)
    {
       std::list<ParentPtr> lp=GetAllParents(ParentPtr(new T(*node->get())));
       return std::list<T>(lp);
    }
    I am looking for a way to return the list without casting.

  2. #2
    Join Date
    May 2007
    Location
    Scotland
    Posts
    1,164

    Re: Inheritance in template methods

    Quote Originally Posted by Gabbie View Post
    I need to return a list of T types that are children of ParentPtr (shared_ptr).

    Code:
    std::list<ParentPtr> GetAllParent(ParentPtr pp)
    {
    }

    Code:
    class U:public Parent{}
    std::list<U> ul=GetAllNodes<U>(Shared_ptr_U);
    and my template method that looks like this

    Code:
    template<class T>
    std::list<T> GetAllNodes(std::shared_ptr<T> node)
    {
       std::list<ParentPtr> lp=GetAllParents(ParentPtr(new T(*node->get())));
       return std::list<T>(lp);
    }
    I am looking for a way to return the list without casting.
    What you are doing is bad design and outright dangerous. Firstly, how do you know that a parent pointer can be down cast to the child type? At the very least you should have a for loop that only inserts pointers into the result set for objects that can be cast to the child type (you can check this via dynamic_cast).

    I would seriously suggest spending some time getting a grip of object orientation and familiarise yourself with design patterns though, because what you are presenting really isn't good design.

    Nonetheless, in answer to your question, you need to make sure you use dynamic casts to ensure that you can in fact down cast safely. Here is an example of some code that will do what you want safely, but I'd suggest that you take another look at the problem that you are trying to solve, because maintaining a list of base pointers and then constantly needing to downcast in order to access the correct behaviour isn't a good solution - alarm bells should be ringing in your head right now! A good polymorphic design shouldn't require down casting, since everything that you need should be accessible via a base pointer or reference. So, I emphasize that I do not condone the code I am providing you, but am merely showing you how to do what you are asking in a "safe" manner. Seriously though, don't use this code, understand the problem better and design the solution accordingly.

    Code:
    #include <iostream>
    #include <memory>
    #include <list>
    
    class vehicle{
    public:
        virtual ~vehicle(){}
    };
    
    class car : public vehicle{};
    class lorry : public vehicle{};
    
    //Here to maintain the lifetime of the vehicle objects referenced in the returned list
    //and provide easy access to the class object of type T
    template <typename T>
    class vehicle_wrapper {
    public:
        vehicle_wrapper(const std::shared_ptr<vehicle>& ptr)
            :vehicle_(get_vehicle(ptr))
            ,vehicle_ptr_(ptr)
        {}
        
        T& get() { return vehicle_; }
        const T& get() const { return vehicle_; }
        
    private:
        static T* get_vehicle(const std::shared_ptr<vehicle>& ptr) {
            if(ptr == nullptr) {
                throw std::runtime_error("pointer is null!");
            }
            return &dynamic_cast<T&>(*ptr);
        }
    
        T* vehicle_;
        std::shared_ptr<vehicle> vehicle_ptr_;
    };
    
    
    class vehicle_list {
    public:
        void add(const std::shared_ptr<vehicle>& v) {
            list_.push_back(v);
        }
        
        template <typename T>
        std::list<vehicle_wrapper<T> > get_vehicles_of_type() {
            std::list<vehicle_wrapper<T> > result;
          
            for(std::shared_ptr<vehicle> v : list_) {
                if(v != nullptr && dynamic_cast<T*>(&*v) != nullptr) {
                    result.push_back(vehicle_wrapper<T>(v));
                }
            }
            return result;
        }
      
    private:
        std::list<std::shared_ptr<vehicle> > list_;
    };
    
    int main() {
        vehicle_list vlist;
        vlist.add(std::shared_ptr<vehicle>(new car()));
        vlist.add(std::shared_ptr<vehicle>(new car()));
        vlist.add(std::shared_ptr<vehicle>(new car()));
        vlist.add(std::shared_ptr<vehicle>(new lorry()));
        vlist.add(std::shared_ptr<vehicle>(new lorry()));
        
        std::cout << "num cars: " << vlist.get_vehicles_of_type<car>().size() << std::endl; 
        std::cout << "num lorrys: " << vlist.get_vehicles_of_type<lorry>().size() << std::endl; 
        
        return 0;
    }

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured