I am having some trouble with a tiny piece of code that has me a little confused. I am currently working on a project where speed is important, hence my choice of c++.
I am trying to pass a vector into a function by reference. The vector is of type unique_ptr<int>
and I would like to call push_back()
on the vector to add elements to it. I have made sure that I am calling move()
on the pointer when I pass it into push_back()
but for some reason I get compiler errors telling me that:
static assertion failed: result type must be constructible from value type of input range
This only happens when I pass the vector by reference, rather than by value. I could pass the vector by value, but I would like to avoid unnecessary copying if possible. This error doesnt seem to happen when trying to add copyable objects to either the vector passed by value or reference.
Im using g++ 9.3.0 to compile.
Here is a little snippet that reproduces the error, any help appreciated.
#include <vector>
#include <memory>
using namespace std;
void appendToVectorVal(vector<unique_ptr<int>> vectorVal){
unique_ptr<int> toPush = make_unique<int>(1);
vectorVal.push_back(move(toPush)); // does compile
}
void appendToVectorRef(vector<unique_ptr<int>>& vectorRef){
unique_ptr<int> toPush = make_unique<int>(1);
vectorRef.push_back(move(toPush)); // doesnt compile
}
int main() {
vector<unique_ptr<int>> ptrVector;
appendToVectorVal(ptrVector);
appendToVectorRef(ptrVector);
return 0;
}
This snippet fails to compile simply because you are passing a vector of unique_ptr
by value to the appendToVectorVal
function. passing a vector by value means you call the copy constructor of std::vector
, which call the constructor of every element the vector holds. But the copy constructor of std::unique_ptr
is deleted.
In fact the following snippet compiles successfully:
#include <vector>
#include <memory>
using namespace std;
void appendToVectorRef(vector<unique_ptr<int>>& vectorRef){
unique_ptr<int> toPush = make_unique<int>(1);
vectorRef.push_back(move(toPush));
}
int main() {
vector<unique_ptr<int>> ptrVector;
appendToVectorRef(ptrVector);
return 0;
}
Applying push_back
with a moved object is valid. It calls the void push_back( T&& value );
version (In C++20 qualified with a constexpr
), which only require T
to be move constructible.