When run under Valgrind, the first error I see is
Invalid read of size 8
at 0x4CCE92D: __dynamic_cast (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.22)
by 0x109139: _ZZ4mainENKUlOT_E_clIRSt10unique_ptrI8DrawableSt14default_deleteIS4_EEEEDaS0_ (43706186.cpp:27)
by 0x10917B: _ZN9__gnu_cxx5__ops10_Iter_predIZ4mainEUlOT_E_EclINS_17__normal_iteratorIPSt10unique_ptrI8DrawableSt14default_deleteIS9_EESt6vectorISC_SaISC_EEEEEEbS2_ (predefined_ops.h:241)
by 0x10902D: _ZSt11__remove_ifIN9__gnu_cxx17__normal_iteratorIPSt10unique_ptrI8DrawableSt14default_deleteIS3_EESt6vectorIS6_SaIS6_EEEENS0_5__ops10_Iter_predIZ4mainEUlOT_E_EEESE_SE_SE_T0_ (stl_algo.h:866)
by 0x108F78: _ZSt9remove_ifIN9__gnu_cxx17__normal_iteratorIPSt10unique_ptrI8DrawableSt14default_deleteIS3_EESt6vectorIS6_SaIS6_EEEEZ4mainEUlOT_E_ESC_SC_SC_T0_ (stl_algo.h:937)
by 0x108EBC: main (43706186.cpp:25)
Address 0x5892dc0 is 0 bytes inside a block of size 16 free'd
at 0x4A0A2DB: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
by 0x109BFC: Derived::~Derived() (43706186.cpp:15)
by 0x109D21: std::default_delete<Drawable>::operator()(Drawable*) const (unique_ptr.h:76)
by 0x10A7C4: std::unique_ptr<Drawable, std::default_delete<Drawable> >::reset(Drawable*) (unique_ptr.h:347)
by 0x10A39D: std::unique_ptr<Drawable, std::default_delete<Drawable> >::operator=(std::unique_ptr<Drawable, std::default_delete<Drawable> >&&) (unique_ptr.h:254)
by 0x109062: _ZSt11__remove_ifIN9__gnu_cxx17__normal_iteratorIPSt10unique_ptrI8DrawableSt14default_deleteIS3_EESt6vectorIS6_SaIS6_EEEENS0_5__ops10_Iter_predIZ4mainEUlOT_E_EEESE_SE_SE_T0_ (stl_algo.h:868)
by 0x108F78: _ZSt9remove_ifIN9__gnu_cxx17__normal_iteratorIPSt10unique_ptrI8DrawableSt14default_deleteIS3_EESt6vectorIS6_SaIS6_EEEEZ4mainEUlOT_E_ESC_SC_SC_T0_ (stl_algo.h:937)
by 0x108EBC: main (43706186.cpp:25)
Block was alloc'd at
at 0x4A0921F: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
by 0x10942E: std::_MakeUniq<Derived>::__single_object std::make_unique<Derived>() (unique_ptr.h:791)
by 0x108DE2: main (43706186.cpp:21)
From this, we can see that one of the elements added to the array was deleted, but we still attempted the dynamic_cast in the lambda through the captured pointer (selected).
If we move the cast outside erase-remove call, then the dynamic_cast is performed only once, before the element is removed:
auto const s2 = dynamic_cast<Drawable*>(selected);
vec.erase(std::remove_if(vec.begin(), vec.end(),
[s2](auto&& ptr) {
return ptr.get() == s2;
}), vec.end());
This version runs to completion with no warnings from Valgrind.
In passing, note that you can write the lambda to accept const auto&, as you don't intend to modify the elements.