I am trying to use polymorphism to represent a tree of sorts (terminal and non-terminal nodes for a parser). One of the classes Node
holds a vector of smart pointers to subclasses of Base
. I'd like to add more nodes to this vector with a method that accepts just a Node
reference without having to create the smart pointer outside of the class (or is this terrible practice?).
The void addNode(const std::unique_ptr<Node> &&node)
overload works, but I'd like to use the
void addNode(const Node &&node)
overload.
No matter what I do, I can't seem to create and move this smart pointer into the vector without breaking the copy elision rule or calling the copy constructor of Node and I'm not exactly sure why. It looks like make_unique
is always invoking the copy-constructor of Node. I've tried using these statements:
nodes.push_back(std::make_unique<Node>(node));
Gives a compiler error call to implicitly-deleted copy constructor
. This makes sense, thought I just had to std::move
it.
nodes.push_back(std::move(std::make_unique<Node>(node)));
Same error as above, also: moving a temporary object prevents copy elision
.
nodes.push_back(std::make_unique<Node>(std::move(node)));
Just gives the call to implicitly-deleted copy constructor
.
nodes.push_back(std::move(std::make_unique<Node>(std::move(node))));
Even tried this, which gives both errors as well.
Here is my repro:
#include <iostream>
#include <string>
#include <vector>
class Base {};
class Node;
typedef std::vector<std::unique_ptr<Base> > Nodes;
class Node : public Base {
Nodes nodes;
public:
Node() {};
void addNode(const Node &&node) {
nodes.push_back(std::make_unique<Node>(node));
//nodes.push_back(std::move(std::make_unique<Node>(node)));
//nodes.push_back(std::make_unique<Node>(std::move(node)));
//nodes.push_back(std::move(std::make_unique<Node>(std::move(node))));
}
void addNode(std::unique_ptr<Node> &&node) {
nodes.push_back(std::move(node));
}
};
int main()
{
Node rootNode;
rootNode.addNode(Node());
rootNode.addNode(std::make_unique<Node>());
return 0;
}
I am compiling on MacOS with Clang++ and C++20.