Home > Software engineering >  Collection of template child classes
Collection of template child classes

Time:03-03

I'm still new to template classes. But I have a parent class and then a template child class.

namespace Foo::Bar {
    class BaseClass {
        // No declarations
    };

    template<typename ChildClassType>
    class ChildClass : public BaseClass {
        public:
            /// Public declarations
        private:
            // Private Members
    };
}

Edit: Including further information about the ChildClassType So I have several structs that will use this template class.

struct foofoo {
// Declarations
}

struct barbar {
// Declarations
}

I want to be able to have a vector of multiple Child classes of each type so I used

std::vector<std::unique_ptr<BaseClass>> allChildTypeVector;
std::unique_ptr<ChildClass<foofoo>> childPtr;
allChildTypeVectors.push_back(childPtr);

Which is recommended by several other answers on here. But I am getting.

no instance of overloaded function "std::vector<_Tp, _Alloc>::push_back ....." matches the argument list

This same error is given if I do allChildTypeVectors.push_back(new ChildClass<ChildClassType>);

I know something is going wrong with my types but I can't seem to figure it out.

CodePudding user response:

std::unique_ptrs cannot be copied. If you could copy them they would not be unique. Hence you get the error when you try to call push_back. If you do have a std::unique_ptr<ChildClass<foofoo>> to be placed in the vector you can move it:

#include <string>
#include <memory>
#include <vector>

class BaseClass {};

template<typename ChildClassType>
class ChildClass : public BaseClass {};   

struct foofoo {};
   
int main() {
    std::vector<std::unique_ptr<BaseClass>> allChildTypeVector;
    std::unique_ptr<ChildClass<foofoo>> childPtr;
    allChildTypeVector.push_back(std::move(childPtr));
}

Note that this has nothing to do with ChildClass being a template. There are no template classes. ChildClass is a class template, and ChildClass<foofoo> is a class.


So then why does allChildTypeVectors.push_back(new ChildClass); not work? Because that would be the ideal solution.

The constructor that takes a raw pointer is explicit. See here: https://en.cppreference.com/w/cpp/memory/unique_ptr/unique_ptr. You can call the constructor explicitly or use std::make_unique:

allChildTypeVector.push_back(std::unique_ptr<ChildClass<foofoo>>(new ChildClass<foofoo>));
allChildTypeVector.push_back(std::make_unique<ChildClass<foofoo>>());

A non-explicit constructor would be less than ideal because then raw pointers would implicitly convert to unique_ptrs unnoticed. For details I refer you to Why is unique_ptr<T>(T*) explicit?.

  • Related