vc++ 2010/2012: std::vector of a struct containing unique_ptr compiler error
-
13-12-2019 - |
Question
The following code generates the compiler error below (after the code), but not if the vector contains unique_ptr's directly (see commented code lines). Any ideas why?
The question is more concerned with the code block in the "#if 1" block, the "#else" block generates the error (after changing "#if 1" to "#if 0") that is similar, but is more expected.
// MoveSemantics.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <memory>
#include <vector>
typedef std::unique_ptr<int> upi;
struct S
{
S() : p(new int(123)) {}
S(S&& s) : p( std::move(s.p) ) {} // NB: the move constructor is supposed to be used? (but not)
upi p;
};
#if 1
void test()
{
//std::vector<S> vs; // Okay
//std::vector<upi> vupi(10); // Okay
std::vector<S> vs(10); // Error! why in the hell does the compiler want to generate a copy constructor here??
}
#else
void test()
{
std::vector<S> vs;
vs.push_back( S() );
const S& s = vs.front();
//S& s = vs.front(); // fine!
S s1 = std::move(s); // Error, but expected
}
#endif
int _tmain(int argc, _TCHAR* argv[])
{
return 0;
}
Compiler Error:
1> error C2248: 'std::unique_ptr<_Ty>::operator =' : cannot access private member declared in class 'std::unique_ptr<_Ty>'
1> with
1> [
1> _Ty=int
1> ]
1> c:\program files\microsoft visual studio 11.0\vc\include\memory(1435) : see declaration of 'std::unique_ptr<_Ty>::operator ='
1> with
1> [
1> _Ty=int
1> ]
1> This diagnostic occurred in the compiler generated function 'S &S::operator =(const S &)'
Solution
This looks like a bug in your std::lib. I'm sure it got here because of the history of the evolving vector
specification.
In C++98/03 vector
had this constructor:
explicit vector(size_type n, const T& value = T(), const Allocator& = Allocator());
And the specification was that the T
would be default constructed once and then copy constructed n
times when called with the latter two arguments defaulted.
In C++11 this got changed to:
explicit vector(size_type n);
vector(size_type n, const T& value, const Allocator& = Allocator());
The spec for the 2nd constructor didn't change. But the first did: It should default construct T n
times, and not copy (or move) it at all.
I would have expected the error message to say that the deleted or private copy constructor of unique_ptr
was being used. That would have indicated that the vector
was following the C++98/03 spec, and simply hasn't been updated yet.
But since the diagnostic is complaining about unique_ptr
's copy assignment instead, then it looks like the vector
has been updated, but incorrectly. It sounds like it is using this signature from C++98/03:
explicit vector(size_type n, const T& value = T(), const Allocator& = Allocator());
and default constructing n
T
's, and then assigning value
to those n
T
's.
OTHER TIPS
You did not include a move assignment operator, which is part of the vector
requirements, only a move constructor.