I was expecting the following code to compile whenever I define VECTOR_OF_SHAPES, but it didn't, and I don't understand why.
The idea is to test polymorphism using a container of smart pointers. I've step into similar answers regarding this topic and they point to the need of move constructors & move assignment operators, and that's why I wrote some code around RULE_OF_5 but it still the 'use of deleted function' error arises.
I've tried the code with g++, clang and cpp.sh, all returning nearly the same output.
#include <iostream>
#include <memory>
#include <vector>
#define inherits_from : public
class Shape
{
public:
Shape() { std::cout << __FUNCTION__ << "()" << std::endl; }
#ifdef RULE_OF_5
Shape(const Shape&) {}
Shape(Shape&&) {}
Shape& operator=(const Shape&) { return *this; }
Shape& operator=(Shape&&) { return *this; }
#endif
virtual ~Shape() { std::cout << __FUNCTION__ << "()" << std::endl; }
virtual void Draw() = 0;
};
class Circle inherits_from Shape
{
public:
virtual void Draw() { std::cout << "Drawing a circle" << std::endl; }
};
class Triangle inherits_from Shape
{
public:
virtual void Draw() { std::cout << "Drawing a triangle" << std::endl; }
};
class Square inherits_from Shape
{
public:
virtual void Draw() { std::cout << "Drawing a square" << std::endl; }
};
void test()
{
auto shape0 = std::make_unique<Circle>();
std::unique_ptr<Shape> shape1 = std::make_unique<Triangle>();
auto shapes = std::vector<std::unique_ptr<Shape>>();
#ifdef VECTOR_OF_SHAPES
auto shapes2 = std::vector<std::unique_ptr<Shape>>
{
std::make_unique<Circle>()
}; // <- error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = Shape; _Dp = std::default_delete<Shape>]’...
#endif
}
int main()
{
test();
return 0;
}
Compilation command:
g++-8 -DVECTOR_OF_SHAPES -DRULE_OF_5 -ggdb -O0 -std=c++14 -Wall -Wextra -fPIC -pedantic polymorphic-test.cpp -o polymorphic-test
Full compiler output:
In file included from /usr/include/c++/8/memory:64,
from polymorphic-test.cpp:3:
/usr/include/c++/8/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_T1*, _Args&& ...) [with _T1 = std::unique_ptr<Shape>; _Args = {const std::unique_ptr<Shape, std::default_delete<Shape> >&}]’:
/usr/include/c++/8/bits/stl_uninitialized.h:83:18: required from ‘static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = const std::unique_ptr<Shape>*; _ForwardIterator = std::unique_ptr<Shape>*; bool _TrivialValueTypes = false]’
/usr/include/c++/8/bits/stl_uninitialized.h:134:15: required from ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = const std::unique_ptr<Shape>*; _ForwardIterator = std::unique_ptr<Shape>*]’
/usr/include/c++/8/bits/stl_uninitialized.h:289:37: required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = const std::unique_ptr<Shape>*; _ForwardIterator = std::unique_ptr<Shape>*; _Tp = std::unique_ptr<Shape>]’
/usr/include/c++/8/bits/stl_vector.h:1469:33: required from ‘void std::vector<_Tp, _Alloc>::_M_range_initialize(_ForwardIterator, _ForwardIterator, std::forward_iterator_tag) [with _ForwardIterator = const std::unique_ptr<Shape>*; _Tp = std::unique_ptr<Shape>; _Alloc = std::allocator<std::unique_ptr<Shape> >]’
/usr/include/c++/8/bits/stl_vector.h:519:2: required from ‘std::vector<_Tp, _Alloc>::vector(std::initializer_list<_Tp>, const allocator_type&) [with _Tp = std::unique_ptr<Shape>; _Alloc = std::allocator<std::unique_ptr<Shape> >; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<std::unique_ptr<Shape> >]’
polymorphic-test.cpp:51:3: required from here
/usr/include/c++/8/bits/stl_construct.h:75:7: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = Shape; _Dp = std::default_delete<Shape>]’
{ ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/8/memory:80,
from polymorphic-test.cpp:3:
/usr/include/c++/8/bits/unique_ptr.h:394:7: note: declared here
unique_ptr(const unique_ptr&) = delete;
^~~~~~~~~~
So, can anyone explain why whenever I define VECTOR_OF_SHAPES, the compilation fails and how to fix the code? Thanks in advance
Note: My idea of answer would be to find a way of constructing the vector with an initializer list, and not to use push_back() or emplace_back()
Aucun commentaire:
Enregistrer un commentaire