При написании ответа на вопрос this я столкнулся с интересной ситуацией - вопрос демонстрирует сценарий, когда нужно было бы поместить класс в контейнер STL, но не удалось сделайте это из-за отсутствующего оператора конструктора/перемещения конструктора/назначения. В этом конкретном случае ошибка срабатывает std::vector::resize
. Я сделал быстрый фрагмент в качестве решения и увидел еще один ответ, который предоставил конструктор перемещения вместо оператора присваивания и конструктора копирования, как и у меня. Было то, что другой ответ не компилировался в VS 2012, в то время как clang/gcc были довольны обоими подходами.
Во-первых:
// 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;
}
Во-вторых:
// 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;
}
Чтобы понять, что происходит, я просмотрел источники STL в VS 2012 и увидел, что он действительно вызывает оператор присваивания перемещения, поэтому мой образец работал (у меня нет машины Linux, доступной для понимания того, что происходит on в clang/gcc), а другой нет, поскольку у него был только конструктор копии перемещения.
Итак, это создало следующий вопрос: может ли компилятор свободно решить, как реализовать STL-методы (в данном случае std::vector::resize
), так как радикально разные реализации могут вызывать непереносимый код? Или это просто ошибка VS 2012?