@@ -102,8 +102,14 @@ class vector {
102102 iterator insert (const_iterator pos, const_reference val);
103103 iterator insert (const_iterator pos, value_type &&val);
104104 iterator insert (const_iterator pos, size_type n, const_reference val);
105- template <class InputIter >
105+ template <std::forward_iterator ForwardIter>
106+ requires std::constructible_from<T, std::iter_reference_t <ForwardIter>>
107+ iterator insert (const_iterator pos, ForwardIter first, ForwardIter last);
108+ template <std::input_iterator InputIter>
109+ requires std::constructible_from<T, std::iter_reference_t <InputIter>> &&
110+ (!std::forward_iterator<InputIter>)
106111 iterator insert (const_iterator pos, InputIter first, InputIter last);
112+ iterator insert (const_iterator pos, std::initializer_list<T> init);
107113 template <class ... Args>
108114 iterator emplace (const_iterator pos, Args &&...args);
109115 iterator erase (const_iterator pos);
@@ -136,6 +142,8 @@ class vector {
136142
137143 void destruct (pointer new_last);
138144
145+ void move_to_insert (pointer first, pointer last, pointer dst_first);
146+
139147private:
140148 Alloc m_alloc;
141149 pointer m_begin = nullptr ;
@@ -586,7 +594,7 @@ void vector<T, Alloc>::reserve(size_type n) {
586594 }
587595
588596 m_begin = new_begin;
589- m_end = new_end;
597+ m_end = new_end;
590598 m_cap = new_cap;
591599 }
592600}
@@ -640,12 +648,17 @@ vector<T, Alloc>::insert(const_iterator pos, const_reference val) {
640648 if (p == m_end) {
641649 this ->construct (1 , val);
642650 } else {
643- alloc_traits::consturct (m_alloc, m_end, std::move (*(m_end - 1 )));
644- ++m_end;
645- std::move_backward (p, m_end - 2 , m_end - 1 );
651+ this ->move_to_insert (p, m_end, p + 1 );
652+
653+ const_pointer pval = std::pointer_traits<pointer>::pointer_to (val);
654+ const_pointer pp = std::to_address (p);
655+ const_pointer pend = std::to_address (m_end);
656+ if (!(pp <= pval && pval < pend)) {
657+ pval += 1 ;
658+ }
659+
646660 *p = val;
647661 }
648- return iterator (p);
649662 } else {
650663 size_type sz = this ->recommend (this ->size () + 1 );
651664 pointer new_begin = alloc_traits::allocate (m_alloc, sz);
@@ -673,9 +686,9 @@ vector<T, Alloc>::insert(const_iterator pos, const_reference val) {
673686 m_begin = new_begin;
674687 m_end = new_end;
675688 m_cap = new_cap;
676-
677- return iterator (m_begin + offset);
678689 }
690+
691+ return iterator (p);
679692}
680693
681694template <class T , class Alloc >
@@ -688,20 +701,17 @@ vector<T, Alloc>::insert(const_iterator pos, value_type &&val) {
688701 alloc_traits::construct (m_alloc, p, std::move (val));
689702 ++m_end;
690703 } else {
691- alloc_traits::construct (m_alloc, m_end, std::move (*(m_end - 1 )));
692- ++m_end;
693- std::move_backward (p, m_end - 2 , m_end - 1 );
704+ this ->move_to_insert (p, m_end, p + 1 );
694705 *p = std::move (val);
695706 }
696- return iterator (p);
697707 } else {
698708 size_type sz = this ->recommend (this ->size () + 1 );
699709 pointer new_begin = alloc_traits::allocate (m_alloc, sz);
700710 pointer new_end = new_begin;
701711 pointer new_cap = new_begin + sz;
702712
703713 if constexpr (std::is_nothrow_move_constructible_v<value_type>) {
704- new_end = std::uninitialized_move (m_begin, p, new_begin);
714+ new_end = std::uninitialized_move (m_begin, p, new_begin);
705715 } else {
706716 new_end = std::uninitialized_copy (m_begin, p, new_begin);
707717 }
@@ -710,7 +720,7 @@ vector<T, Alloc>::insert(const_iterator pos, value_type &&val) {
710720 ++new_end;
711721
712722 if constexpr (std::is_nothrow_move_constructible_v<value_type>) {
713- new_end = std::uninitialized_move (p, m_end, new_end);
723+ new_end = std::uninitialized_move (p, m_end, new_end);
714724 } else {
715725 new_end = std::uninitialized_copy (p, m_end, new_end);
716726 }
@@ -721,20 +731,157 @@ vector<T, Alloc>::insert(const_iterator pos, value_type &&val) {
721731 m_begin = new_begin;
722732 m_end = new_end;
723733 m_cap = new_cap;
724-
725- return iterator (m_begin + offset);
726734 }
735+ return iterator (p);
727736}
728737
729738template <class T , class Alloc >
730739typename vector<T, Alloc>::iterator
731740vector<T, Alloc>::insert(const_iterator pos, size_type n, const_reference val) {
741+ size_type offset = static_cast <size_type>(std::distance (this ->begin (), pos));
742+ pointer p = m_begin + offset;
743+ if (n > 0 ) {
744+ if (n <= static_cast <size_type>(m_cap - m_end)) {
745+ pointer old_end = m_end;
746+ size_type old_n = n;
747+
748+ size_type dx = static_cast <size_type>(m_end - p);
749+ if (n > dx) {
750+ this ->construct (n - dx, val);
751+ n = dx;
752+ }
753+
754+ if (n > 0 ) {
755+ this ->move_to_insert (p, old_end, p + old_n);
756+
757+ const_pointer pval = std::pointer_traits<pointer>::pointer_to (val);
758+ const_pointer pp = std::to_address (p);
759+ const_pointer pend = std::to_address (m_end);
760+ if (!(pp <= pval && pval < pend)) {
761+ pval += old_n;
762+ }
763+ std::fill_n (p, n, *pval);
764+ }
765+ } else {
766+ size_type sz = this ->recommend (this ->size () + n);
767+ pointer new_begin = alloc_traits::allocate (m_alloc, sz);
768+ pointer new_end = new_begin;
769+ pointer new_cap = new_begin + sz;
770+
771+ if constexpr (std::is_nothrow_move_constructible_v<value_type>) {
772+ new_end = std::uninitialized_move (m_begin, p, new_begin);
773+ } else {
774+ new_end = std::uninitialized_copy (m_begin, p, new_begin);
775+ }
776+
777+ for (size_type i = 0 ; i < n; ++i) {
778+ alloc_traits::construct (m_alloc, new_end, val);
779+ ++new_end;
780+ }
781+
782+ if constexpr (std::is_nothrow_move_constructible_v<value_type>) {
783+ new_end = std::uninitialized_move (p, m_end, new_end);
784+ } else {
785+ new_end = std::uninitialized_copy (p, m_end, new_end);
786+ }
787+
788+ this ->destruct (m_begin);
789+ this ->deallocate ();
790+
791+ m_begin = new_begin;
792+ m_end = new_end;
793+ m_cap = new_cap;
794+ }
795+ }
796+
797+ return iterator (p);
798+ }
799+
800+ template <class T , class Alloc >
801+ template <std::forward_iterator ForwardIter>
802+ requires std::constructible_from<T, std::iter_reference_t <ForwardIter>>
803+ typename vector<T, Alloc>::iterator vector<T, Alloc>::insert(
804+ const_iterator pos, ForwardIter first, ForwardIter last
805+ ) {
806+ size_type offset = static_cast <size_type>(std::distance (this ->begin (), pos));
807+ pointer p = m_begin + offset;
808+
809+ difference_type n = std::distance (first, last);
810+
811+ if (n > 0 ) {
812+ if (n <= static_cast <size_type>(m_cap - m_end)) {
813+ pointer old_end = m_end;
814+
815+ size_type dx = static_cast <size_type>(m_end - p);
816+ if (n > dx) {
817+ ForwardIter m = std::next (first, dx);
818+ this ->construct (m, last, n - dx);
819+ n = dx;
820+ }
821+ if (n > 0 ) {
822+ this ->move_to_insert (p, old_end, p + n);
823+ std::copy_n (first, n, p);
824+ }
825+ } else {
826+ size_type sz = this ->recommend (this ->size () + n);
827+ pointer new_begin = alloc_traits::allocate (m_alloc, sz);
828+ pointer new_end = new_begin;
829+ pointer new_cap = new_begin + sz;
830+
831+ if constexpr (std::is_move_constructible_v<value_type>) {
832+ new_end = std::uninitialized_move (m_begin, p, new_begin);
833+ } else {
834+ new_end = std::uninitialized_copy (m_begin, p, new_begin);
835+ }
836+
837+ for (size_type i = 0 ; i < n; ++i) {
838+ alloc_traits::construct (m_alloc, new_end, *first);
839+ ++new_end;
840+ ++first;
841+ }
842+
843+ if constexpr (std::is_move_constructible_v<value_type>) {
844+ new_end = std::uninitialized_move (p, m_end, new_end);
845+ } else {
846+ new_end = std::uninitialized_copy (p, m_end, new_end);
847+ }
848+
849+ this ->destruct (m_begin);
850+ this ->deallocate ();
851+
852+ m_begin = new_begin;
853+ m_end = new_end;
854+ m_cap = new_cap;
855+ }
856+ }
857+
858+ return iterator (p);
859+ }
860+
861+ template <class T , class Alloc >
862+ template <std::input_iterator InputIter>
863+ requires std::constructible_from<T, std::iter_reference_t <InputIter>> &&
864+ (!std::forward_iterator<InputIter>)
865+ typename vector<T, Alloc>::iterator
866+ vector<T, Alloc>::insert(const_iterator pos, InputIter first, InputIter last) {
867+ size_type offset = static_cast <size_type>(std::distance (this ->begin (), pos));
868+ pointer p = m_begin + offset;
869+ pointer old_end = m_end;
870+
871+ for (; first != last; ++first) {
872+ this ->emplace_back (*first);
873+ }
874+
875+ std::rotate (p, old_end, m_end);
876+
877+ return iterator (p);
732878}
733879
734880template <class T , class Alloc >
735- template <class InputIter >
736881typename vector<T, Alloc>::iterator
737- vector<T, Alloc>::insert(const_iterator pos, InputIter first, InputIter last) {}
882+ vector<T, Alloc>::insert(const_iterator pos, std::initializer_list<T> init) {
883+ return insert (pos, init.begin (), init.end ());
884+ }
738885
739886/* -------------------------------------------------------------------------- */
740887/* private member functions */
@@ -816,4 +963,20 @@ void vector<T, Alloc>::destruct(pointer new_last) {
816963 }
817964 m_end = new_last;
818965}
966+
967+ template <class T , class Alloc >
968+ void vector<T, Alloc>::move_to_insert(
969+ pointer from_s, pointer from_e, pointer to
970+ ) {
971+ pointer from_mid = from_s + (m_end - to);
972+ pointer new_end = m_end;
973+ for (; from_mid < from_e; ++from_mid, ++new_end) {
974+ alloc_traits::construct (m_alloc, new_end, std::move (*from_mid));
975+ }
976+
977+ std::move_backward (from_s, from_mid, m_end);
978+
979+ m_end = new_end;
980+ }
981+
819982} // namespace tinystl
0 commit comments