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_ptr
s 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_ptr
s unnoticed. For details I refer you to Why is unique_ptr<T>(T*) explicit?.