Std::unique_ptr<uint8_t[]> jako atrybut klasy.

0

Witajcie,

Mam klase Mipmap: https://github.com/patrykbajos/ZinotEngine/blob/master/src/zinot/tools/textool/conv/Mipmap.hpp. Używałem jej w ten sposób:

Mipmap mipmap;

mipmap.createFromFiBitmap(fiBitmap, destWidth, destHeight,
						0, it, configuration.getMipmapFilter());

if(mipmap.getData() == nullptr)
	return false;

mipmaps.push_back(mipmap);

mipmaps to std::vector

Chyba to powoduje problem. Dostaję taką litanię błędów:

 [ 58%] Building CXX object CMakeFiles/Textool.dir/src/zinot/tools/textool/conv/Mipmap.cpp.o
In file included from /usr/include/x86_64-linux-gnu/c++/4.9/bits/c++allocator.h:33:0,
                 from /usr/include/c++/4.9/bits/allocator.h:46,
                 from /usr/include/c++/4.9/vector:61,
                 from /home/patryk/ClionProjects/BennuEngine/src/zinot/tools/textool/conv/PngConverter.hpp:8,
                 from /home/patryk/ClionProjects/BennuEngine/src/zinot/tools/textool/conv/PngConverter.cpp:5:
/usr/include/c++/4.9/ext/new_allocator.h: In instantiation of ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = Zinot::Textool::Mipmap; _Args = {const Zinot::Textool::Mipmap&}; _Tp = Zinot::Textool::Mipmap]’:
/usr/include/c++/4.9/bits/alloc_traits.h:253:4:   required from ‘static std::_Require<typename std::allocator_traits<_Alloc>::__construct_helper<_Tp, _Args>::type> std::allocator_traits<_Alloc>::_S_construct(_Alloc&, _Tp*, _Args&& ...) [with _Tp = Zinot::Textool::Mipmap; _Args = {const Zinot::Textool::Mipmap&}; _Alloc = std::allocator<Zinot::Textool::Mipmap>; std::_Require<typename std::allocator_traits<_Alloc>::__construct_helper<_Tp, _Args>::type> = void]’
/usr/include/c++/4.9/bits/alloc_traits.h:399:57:   required from ‘static decltype (_S_construct(__a, __p, (forward<_Args>)(std::allocator_traits::construct::__args)...)) std::allocator_traits<_Alloc>::construct(_Alloc&, _Tp*, _Args&& ...) [with _Tp = Zinot::Textool::Mipmap; _Args = {const Zinot::Textool::Mipmap&}; _Alloc = std::allocator<Zinot::Textool::Mipmap>; decltype (_S_construct(__a, __p, (forward<_Args>)(std::allocator_traits::construct::__args)...)) = <type error>]’
/usr/include/c++/4.9/bits/stl_vector.h:918:34:   required from ‘void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = Zinot::Textool::Mipmap; _Alloc = std::allocator<Zinot::Textool::Mipmap>; std::vector<_Tp, _Alloc>::value_type = Zinot::Textool::Mipmap]’
/home/patryk/ClionProjects/BennuEngine/src/zinot/tools/textool/conv/PngConverter.cpp:108:29:   required from here
/usr/include/c++/4.9/ext/new_allocator.h:120:4: error: use of deleted function ‘Zinot::Textool::Mipmap::Mipmap(const Zinot::Textool::Mipmap&)’
  { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
    ^
In file included from /home/patryk/ClionProjects/BennuEngine/src/zinot/tools/textool/conv/PngConverter.hpp:12:0,
                 from /home/patryk/ClionProjects/BennuEngine/src/zinot/tools/textool/conv/PngConverter.cpp:5:
/home/patryk/ClionProjects/BennuEngine/src/zinot/tools/textool/conv/Mipmap.hpp:17:9: note: ‘Zinot::Textool::Mipmap::Mipmap(const Zinot::Textool::Mipmap&)’ is implicitly deleted because the default definition would be ill-formed:
   class Mipmap
         ^
/home/patryk/ClionProjects/BennuEngine/src/zinot/tools/textool/conv/Mipmap.hpp:17:9: error: use of deleted function ‘std::unique_ptr<_Tp [], _Dp>::unique_ptr(const std::unique_ptr<_Tp [], _Dp>&) [with _Tp = unsigned char; _Dp = std::default_delete<unsigned char []>]’
In file included from /usr/include/c++/4.9/memory:81:0,
                 from /home/patryk/ClionProjects/BennuEngine/src/zinot/tools/textool/conv/PngConverter.hpp:9,
                 from /home/patryk/ClionProjects/BennuEngine/src/zinot/tools/textool/conv/PngConverter.cpp:5:
/usr/include/c++/4.9/bits/unique_ptr.h:598:7: note: declared here
       unique_ptr(const unique_ptr&) = delete;
       ^

Całe repo: https://github.com/patrykbajos/ZinotEngine.

5

Proste, unique_ptr nie może być kopiowany, a jeśli jeden z elementów klasy jest niekopiowalny to nie zostanie dla niej wygenerowany domyślny konstruktor kopiujący.

mipmaps.push_back(mipmap);mipmaps.push_back(std::move(mipmap));
Powinno pomóc.

3

Użyj push back z move / emplace_back.

0

Czyli muszę dla Mipmap zrobić konstruktor kopiujący?

1

Nie musisz. Przeczytaj odpowiedzi jeszcze raz.

2

Ok, możliwe, że przeceniłem Twoją znajomość biblioteki standardowej. unique_ptr - zwróć uwagę na "unique" - z założenia jest jedynym obiektem/wskaźnikiem wskazującym na dane/obiekty. Nie możesz go skopiować - bo byś miał więcej niż jeden obiekt wskazujący na te same dane, możesz go tylko przenieść (ahem, move). Po przeniesieniu, oryginalny obiekt (przynajmniej w bibliotece standardowej) zostaje w "valid but unspecified state" - w tym przypadku jest to null pointer.

Jeśli potrzebujesz dostępu do danych weź sobie do obserwacji zwykły wskaźnik.

0

@kq, już ogarnąłem te && i move constructor. Zobaczyłem w docu że push_back ma wydanie z &&, a std::move castuje do &&. Problem rozwiązany. Nurtuje mnie tylko to jak jest automatycznie generowany move constructor i destructor jeśli Go sam nie zdefiniuje, ale to napiszę jak będę na kompie.

1

user image

Polecam lekturę: https://blog.feabhas.com/2015/11/becoming-a-rule-of-zero-hero/

Oczywiście jeśli masz członków klasy, którzy są move-only, albo w ogóle nie do ruszenia (std::mutex, Boost.NonCopyable) to kompilator na siłę nic nie wygeneruje.

1 użytkowników online, w tym zalogowanych: 0, gości: 1