deque<_Tp, _Alloc>::
_M_emplace_aux(iterator __pos, _Args&&... __args)
{
- value_type __x_copy(std::forward<_Args>(__args)...); // XXX copy
+ // We should construct this temporary while the deque is
+ // in its current state in case something in __args...
+ // depends on that state before shuffling elements around.
+ _Temporary_value __tmp(this, std::forward<_Args>(__args)...);
#else
typename deque<_Tp, _Alloc>::iterator
deque<_Tp, _Alloc>::
__pos = this->_M_impl._M_start + __index;
_GLIBCXX_MOVE_BACKWARD3(__pos, __back2, __back1);
}
- *__pos = _GLIBCXX_MOVE(__x_copy);
+#if __cplusplus >= 201103L
+ *__pos = std::move(__tmp._M_val());
+#else
+ *__pos = __x_copy;
+#endif
return __pos;
}
iterator
_M_insert_aux(iterator __pos, const value_type& __x);
#else
+ struct _Temporary_value
+ {
+ template<typename... _Args>
+ _GLIBCXX20_CONSTEXPR explicit
+ _Temporary_value(deque* __deque, _Args&&... __args) : _M_this(__deque)
+ {
+ _Alloc_traits::construct(_M_this->_M_impl, _M_ptr(),
+ std::forward<_Args>(__args)...);
+ }
+
+ _GLIBCXX20_CONSTEXPR
+ ~_Temporary_value()
+ { _Alloc_traits::destroy(_M_this->_M_impl, _M_ptr()); }
+
+ _GLIBCXX20_CONSTEXPR value_type&
+ _M_val() noexcept { return __tmp_val; }
+
+ private:
+ _GLIBCXX20_CONSTEXPR _Tp*
+ _M_ptr() noexcept { return std::__addressof(__tmp_val); }
+
+ union
+ {
+ _Tp __tmp_val;
+ };
+
+ deque* _M_this;
+ };
+
iterator
_M_insert_aux(iterator __pos, const value_type& __x)
{ return _M_emplace_aux(__pos, __x); }
--- /dev/null
+// { dg-do run { target c++11 } }
+
+// PR libstdc++/118087
+// std::deque::emplace does not do uses-allocator construction
+
+#include <deque>
+#include <scoped_allocator>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+template<typename T>
+using Alloc = __gnu_test::propagating_allocator<T, true>;
+
+struct X
+{
+ using allocator_type = Alloc<int>;
+ X() { }
+ X(const X&) { }
+ X(X&&) { }
+ X(const allocator_type& a) : alloc(a) { }
+ X(const X&, const allocator_type& a) : alloc(a) { }
+ X(X&&, const allocator_type& a) : alloc(a) { }
+
+ X& operator=(const X&) = default;
+
+ allocator_type alloc{-1};
+};
+
+int main()
+{
+ std::deque<X, std::scoped_allocator_adaptor<Alloc<X>>> d(2, Alloc<X>(50));
+ VERIFY(d[0].alloc.get_personality() == 50);
+ VERIFY(d[1].alloc.get_personality() == 50);
+
+ d.emplace(d.begin() + 1);
+ VERIFY(d[1].alloc.get_personality() == 50);
+
+ d.emplace_front();
+ VERIFY(d[0].alloc.get_personality() == 50);
+
+ d.emplace_back();
+ VERIFY(d[d.size() - 1].alloc.get_personality() == 50);
+}