While writing an answer to this question I faced an interesting situation - the question demonstrates the scenario where one would want to put a class in an STL container but fails to do so because of a missing copy constructor/move constructor/assignment operator. In this particular case the error is triggered by std::vector::resize
. I made a quick snippet as a solution and saw another answer that had provided a move constructor instead of an assignment operator and copy constructor as I had. What was interresting that the other answer did not compile in VS 2012, while clang/gcc were happy with both approaches.
First:
// Clang and gcc are happy with this one, VS 2012 is not
#include <memory>
#include <vector>
class FooImpl {};
class Foo
{
std::unique_ptr<FooImpl> myImpl;
public:
Foo( Foo&& f ) : myImpl( std::move( f.myImpl ) ) {}
Foo(){}
~Foo(){}
};
int main() {
std::vector<Foo> testVec;
testVec.resize(10);
return 0;
}
Second:
// Clang/gcc/VS2012 are all happy with this
#include <memory>
#include <vector>
using namespace std;
class FooImpl {};
class Foo
{
unique_ptr<FooImpl> myImpl;
public:
Foo()
{
}
~Foo()
{
}
Foo(const Foo& foo)
{
// What to do with the pointer?
}
Foo& operator= (const Foo& foo)
{
if (this != &foo)
{
// What to do with the pointer?
}
return *this;
}
};
int main(int argc, char** argv)
{
vector<Foo> testVec;
testVec.resize(10);
return 0;
}
To understand what was happening I looked at the STL sources in VS 2012 and saw that it really was invoking the move assignment operator so that is why my sample worked (I don't have a Linux machine accessible to understand what is going on in clang/gcc) and the other did not, since it had only the move copy constructor.
So this created the following question - can the compiler freely decide how to implement STL methods (in this case std::vector::resize
), since radically different implementations could cause non-portable code? Or is this simply a VS 2012 bug?
Standard C++ includes the standard library commonly known as the STL. Every implementation of standard C++ includes the standard library.
Standard Template Library (STL) The Standard Template Library (STL), part of the C++ Standard Library, offers collections of algorithms, containers, iterators, and other fundamental components, implemented as templates, classes, and functions essential to extend functionality and standardization to C++.
Standard Template Library is the latest edition in C++. STL provides programmers to store the data effectively, and do manipulation in stored data. These are the general-purpose templates of classes and functions that help in implementing the basic algorithms and data structures like vector, lists, queue, stack, etc.
Sometimes "STL" is also used to refer to the containers and algorithms parts of the C++ Standard Library adapted from Stepanov's STL. In this documentation, Standard Template Library (STL) refers to the C++ Standard Library as a whole.
Visual C++ 2012 is unable to auto-generate the move constructor and the move assignment operator. A defect that will only be fixed in the upcoming 2015 version.
You can make your first example compile by adding an explicit move assignment operator to Foo
:
#include <memory>
#include <vector>
class FooImpl {};
class Foo
{
std::unique_ptr<FooImpl> myImpl;
public:
Foo( Foo&& f ) : myImpl( std::move( f.myImpl ) ) {}
// this function was missing before:
Foo& operator=( Foo&& f) { myImpl = std::move(f.myImpl); return *this; }
Foo(){}
~Foo(){}
};
int main() {
std::vector<Foo> testVec;
testVec.resize(10);
return 0;
}
As explained in detail by ikh's answer, the standard actually does not require a move assignment operator here. The relevant concepts for vector<T>::resize()
are MoveInsertable and DefaultInsertable, which would have been met by your initial implementation with just the move constructor.
The fact that VC's implementation also requires the move assignment here is a different defect, which was already fixed in VS2013.
Thanks to ikh and dyp for their insightful contributions in this matter.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With