lambda
lambda

Reputation: 1235

C++ A class(not object) Parameter for a Template

I have Derived Classes that inherit from a Base class with virtual functions. Im using smart pointers(shared_ptr) in order to create the objects because i want the objects to be appended into a vector. But i noticed my code to be repetitive with handling to objects to do certain tasks so i thought a template could be solution to improve my code. This is my attempt so far(not the exact code, simplified):

class Base{

    public:
     virtual ~Base(){}
     virtual void display_message() = 0;
};

class DerivedA : public Base{
    DerivedA(){}
};

class DerivedB : public Base{
    DerivedB(){}
};



//THE template- 
//<hold the smart pointer that points to different derived objects>

template<typename T1>

class HandleInstances{
      private:            

         vector<T1> ObjectVector;
         //the iterator

         T1 sp_base;

      public:

        HandleInstance(const T1 & sp){
            sp_base = sp; // set smart pointer
        }
        //somefunctions

        //this is what i need to figure out
        void AddToVector(){
             ObjectVector.push_back(sp_base(new 'The derived class') );
        }



};

The AddToVector functions is the problem here. in order to add an element of an object i have to do this push_back( "the smart pointer"( new "the class" ));. how do i let the template accept the class (not an object) and implement it to the function of push_back() ?

Upvotes: 1

Views: 123

Answers (3)

Matt
Matt

Reputation: 10564

This is a challenging one - why? Because templates operate as a sort of preprocessing step in C++ by dynamically constructing variants of classes based on their template parameter.

In other words, shared_ptr<DerivedA> and shared_ptr<DerivedB> have no relationship to each other whatsoever, because in C++, templates essentially make them like 2 separate class declarations - unrelated types.

The pointers they contain are both descendants of the base class, but the shared_ptrs themselves might as well be a Vector<Bool> and a Foo. It doesn't matter that DerivedA and DerivedB inherit from a single base class, their template-generated classes do not.

That being said, you do have some flexibility: if you put a factory function in your classes' interface, like this:

class DerivedA : public Base{
    public:
    static shared_ptr<DerivedA> construct{
        return shared_ptr<DerivedA>(new DerivedA());
    };
};

....similar for DerivedB

then you can do something like this:

template<typename T>
class HandleInstances{
  private:            

     vector<shared_ptr<T> > ObjectVector;

  public:

    //this is what i need to figure out
    void AddToVector(){
         ObjectVector.push_back(T::construct());
    }
};

and you should be OK. What you're doing is giving each class a function to make up for the fact that the class itself can't be stored to make objects later. Notice:

  1. The template parameter in HandleInstances is the base type, not a shared_ptr type.
  2. Construct is returning different types in DerivedA and DerivedB.
  3. Base has no declaration of construct - because these functions do not return compatible types, they are not inherited from Base.
  4. You still can't mix and match types in your ObjectVector, if that's what you were hoping - but you were never going to be able to do that anyway. (Bonus: it is possible if you use more types to wrap your types and handle this: see boost::any

Upvotes: 0

Some programmer dude
Some programmer dude

Reputation: 409166

You are trying to use an object as a class, and that will not work (unless the object has an operator() that returns the correct object, but I digress).

Try instead:

void AddToVector(){
    ObjectVector.push_back(T1(sp_base));
}

This will create a new object, and invoke the copy-constructor of the new object and pass sp_base to it. So in essence create a copy of sp_base.

Upvotes: 1

Luchian Grigore
Luchian Grigore

Reputation: 258588

Make the function a template as well:

template<typename T2>
void AddToVector(){
    ObjectVector.push_back(smart(new T2));
}

I'm assuming you meant to have a smart pointer in the push_back rether than your member variable sp_base.

Upvotes: 0

Related Questions