@@ -294,6 +294,101 @@ template <typename L> class IntrusiveDList {
294294 // / @return @a limit
295295 iterator erase (const iterator &start, const iterator &limit);
296296
297+ /* * The nth element of the list.
298+ *
299+ * @param n Index of target element.
300+ * @return An iterator to the element, an empty iterator if @a n is too large.
301+ *
302+ * @note This is linear in @a n, use with caution.
303+ */
304+ iterator nth (unsigned n);
305+
306+ /* * Remove and return an initial subsequence.
307+ *
308+ * @param n Number of elements.
309+ * @return The list of elements.
310+ *
311+ * If @a n is more than the length of the list, the entire list is returned.
312+ */
313+ self_type take_prefix (unsigned n);
314+
315+ /* * Remove and return an initial subsequence.
316+ *
317+ * @param n Number of elements.
318+ * @return The list of elements.
319+ *
320+ * If @a n is more than the length of the list @a this is unchanged and an empty list returned.
321+ */
322+ self_type split_prefix (unsigned n);
323+
324+ /* * Remove and return a trailing subsequence.
325+ *
326+ * @param n Number of elements.
327+ * @return The list of elements.
328+ *
329+ * If @a n is more than the length of the list, the entire list is returned.
330+ */
331+ self_type take_suffix (unsigned n);
332+
333+ /* * Remove and return a trailing subsequence.
334+ *
335+ * @param n Number of elements.
336+ * @return The list of elements.
337+ *
338+ * If @a n is more than the length of the list, @a this is unchanged and an empty list returned.
339+ */
340+ self_type split_suffix (unsigned n);
341+
342+ /* * Append a list.
343+ *
344+ * @param src List to append.
345+ * @return @a this
346+ *
347+ * The elements are removed from @a src, which becomes empty.
348+ */
349+ self_type & append (self_type & src);
350+
351+ /* * Prepend a list.
352+ *
353+ * @param src List to prepend.
354+ * @return @a this
355+ *
356+ * The elements are removed from @a src, which becomes empty.
357+ */
358+ self_type & prepend (self_type & src);
359+
360+ /* * Splice in a list after an existing element.
361+ *
362+ * @param target Element in the lsit.
363+ * @param src List to splice.
364+ * @return @a this
365+ */
366+ self_type &insert_after (value_type *target, self_type & src);
367+
368+ /* * Splice in a list before an existing element.
369+ *
370+ * @param target Element in the lsit.
371+ * @param src List to splice.
372+ * @return @a this
373+ */
374+ self_type &insert_before (value_type *target, self_type & src);
375+
376+ /* * Splice in a list after an existing element.
377+ *
378+ * @param target Element in the lsit.
379+ * @param src List to splice.
380+ * @return @a this
381+ */
382+ self_type &insert_after (iterator const &target, self_type & src);
383+
384+ /* * Splice in a list before an existing element.
385+ *
386+ * @param target Element in the lsit.
387+ * @param src List to splice.
388+ * @return @a this
389+ */
390+ self_type &insert_before (iterator const &target, self_type & src);
391+
297392 // / Remove all elements.
298393 // / @note @b No memory management is done!
299394 // / @return This container.
@@ -744,6 +839,58 @@ IntrusiveDList<L>::insert_before(iterator const &target, value_type *v) -> self_
744839 return this ->insert_before (target._v , v);
745840}
746841
842+ template <typename L>
843+ auto
844+ IntrusiveDList<L>::insert_after(value_type *target, self_type & src) -> self_type & {
845+ if (target && src._count > 0 ) {
846+ if (_tail == target) {
847+ this ->append (src);
848+ } else { // invariant - @a target is not tail therefore has a successor.
849+ L::next_ptr (src._tail ) = L::next_ptr (target); // link @a src tail to @a target successor
850+ L::prev_ptr (L::next_ptr (src._tail )) = src._tail ;
851+
852+ L::prev_ptr (src._head ) = target; // link @a src head to @target
853+ L::next_ptr (target) = src._head ;
854+
855+ _count += src._count ;
856+ src.clear ();
857+ }
858+ }
859+ return *this ;
860+ }
861+
862+ template <typename L>
863+ auto
864+ IntrusiveDList<L>::insert_after(iterator const &target, self_type & src) -> self_type & {
865+ return this ->insert_after (target._v , src);
866+ }
867+
868+ template <typename L>
869+ auto
870+ IntrusiveDList<L>::insert_before(value_type *target, self_type & src) -> self_type & {
871+ if (target && src._count > 0 ) {
872+ if (_head == target) {
873+ this ->prepend (src);
874+ } else { // invariant - @a target is not head and therefore has a predecessor.
875+ L::prev_ptr (src._head ) = L::prev_ptr (target); // link @a src head to @a target predecessor
876+ L::next_ptr (L::prev_ptr (target)) = src._head ;
877+
878+ L::next_ptr (src._tail ) = target; // link @a src tail to @a target
879+ L::prev_ptr (target) = src._tail ;
880+
881+ _count += src._count ;
882+ src.clear ();
883+ }
884+ }
885+ return *this ;
886+ }
887+
888+ template <typename L>
889+ auto
890+ IntrusiveDList<L>::insert_before(iterator const &target, self_type & src) -> self_type & {
891+ return this ->insert_before (target._v , src);
892+ }
893+
747894template <typename L>
748895auto
749896IntrusiveDList<L>::erase(value_type *v) -> value_type * {
@@ -887,11 +1034,140 @@ IntrusiveDList<L>::clear() -> self_type & {
8871034 return *this ;
8881035}
8891036
1037+ template <typename L>
1038+ auto
1039+ IntrusiveDList<L>::nth(unsigned int n) -> iterator {
1040+ if (n >= _count) {
1041+ return {};
1042+ }
1043+
1044+ value_type * spot;
1045+ if (n < _count/2 ) { // closer to head, count from there..
1046+ spot = _head;
1047+ while (n-- > 0 ) { spot = L::next_ptr (spot); }
1048+ } else { // count from tail
1049+ spot = _tail;
1050+ unsigned idx = _count - 1 ;
1051+ while (idx-- > n) { spot = L::prev_ptr (spot); }
1052+ }
1053+ return iterator_for (spot);
1054+ }
1055+
1056+ template <typename L>
1057+ auto
1058+ IntrusiveDList<L>::take_prefix(unsigned int n) -> self_type {
1059+
1060+ if (n == 0 ) {
1061+ return {};
1062+ }
1063+
1064+ if (_count <= n) {
1065+ return std::move (*this );
1066+ }
1067+
1068+ // Invariant - there is at least one element that will not be taken.
1069+
1070+ self_type zret;
1071+ value_type * spot = this ->nth (n); // new @a head for @a this
1072+
1073+ zret._count = n;
1074+ zret._head = _head;
1075+ zret._tail = L::prev_ptr (spot);
1076+ L::next_ptr (zret._tail ) = nullptr ;
1077+
1078+ _count -= n;
1079+ _head = spot;
1080+ L::prev_ptr (_head) = nullptr ;
1081+
1082+ return zret;
1083+ }
1084+
1085+ template <typename L>
1086+ auto
1087+ IntrusiveDList<L>::split_prefix(unsigned int n) -> self_type {
1088+ if (n <= _count) {
1089+ return this ->take_prefix (n);
1090+ }
1091+ return {};
1092+ }
1093+
1094+ template <typename L>
1095+ auto
1096+ IntrusiveDList<L>::take_suffix(unsigned int n) -> self_type {
1097+
1098+ if (n == 0 ) {
1099+ return {};
1100+ }
1101+
1102+ if (_count <= n) {
1103+ return std::move (*this );
1104+ }
1105+
1106+ // Invariant - there is at least one element that will not be taken.
1107+
1108+ self_type zret;
1109+ value_type * spot = this ->nth (_count - n - 1 ); // new @a tail for @a this
1110+
1111+ zret._count = n;
1112+ zret._head = L::next_ptr (spot);
1113+ L::prev_ptr (zret._head ) = nullptr ;
1114+ zret._tail = _tail;
1115+
1116+ _count -= n;
1117+ _tail = spot;
1118+ L::next_ptr (_tail) = nullptr ;
1119+
1120+ return zret;
1121+ }
1122+
1123+ template <typename L>
1124+ auto
1125+ IntrusiveDList<L>::split_suffix(unsigned int n) -> self_type {
1126+ if (n <= _count) {
1127+ return this ->take_suffix (n);
1128+ }
1129+ return {};
1130+ }
1131+
1132+ template <typename L>
1133+ auto
1134+ IntrusiveDList<L>::prepend(IntrusiveDList::self_type &src) -> self_type & {
1135+ if (src._count > 0 ) {
1136+ if (_count == 0 ) {
1137+ *this = std::move (src);
1138+ } else {
1139+ L::prev_ptr (_head) = src._tail ;
1140+ L::next_ptr (src._tail ) = _head;
1141+ _count += src._count ;
1142+ _head = src._head ;
1143+ src.clear ();
1144+ }
1145+ }
1146+ return *this ;
1147+ }
1148+
1149+ template <typename L>
1150+ auto
1151+ IntrusiveDList<L>::append(IntrusiveDList::self_type &src) -> self_type & {
1152+ if (src._count > 0 ) {
1153+ if (_count == 0 ) {
1154+ *this = std::move (src);
1155+ } else {
1156+ L::next_ptr (_tail) = src._head ;
1157+ L::prev_ptr (src._head ) = _tail;
1158+ _count += src._count ;
1159+ _tail = src._tail ;
1160+ src.clear ();
1161+ }
1162+ }
1163+ return *this ;
1164+ }
1165+
8901166namespace detail {
8911167// / @cond INTERNAL_DETAIL
8921168// Make @c apply more convenient by allowing the function to take a reference type or pointer type
8931169// to the container elements. The pointer type is the base, plus a shim to convert from a reference
894- // type functor to a pointer pointer type. The complex return type definition forces only one, but
1170+ // type functor to a pointer type. The complex return type definition forces only one, but
8951171// not both, to be valid for a particular functor. This also must be done via free functions and not
8961172// method overloads because the compiler forces a match up of method definitions and declarations
8971173// before any template instantiation.
0 commit comments