219template <
class element_type,
class element_allocator_type = std::allocator<element_type> >
class list :
private element_allocator_type
223 typedef element_type value_type;
224 typedef element_allocator_type allocator_type;
225 typedef unsigned short group_size_type;
227 #ifdef PLF_LIST_ALLOCATOR_TRAITS_SUPPORT
228 typedef typename std::allocator_traits<element_allocator_type>::size_type size_type;
229 typedef typename std::allocator_traits<element_allocator_type>::difference_type difference_type;
230 typedef element_type & reference;
231 typedef const element_type & const_reference;
232 typedef typename std::allocator_traits<element_allocator_type>::pointer pointer;
233 typedef typename std::allocator_traits<element_allocator_type>::const_pointer const_pointer;
235 typedef typename element_allocator_type::size_type size_type;
236 typedef typename element_allocator_type::difference_type difference_type;
237 typedef typename element_allocator_type::reference reference;
238 typedef typename element_allocator_type::const_reference const_reference;
239 typedef typename element_allocator_type::pointer pointer;
240 typedef typename element_allocator_type::const_pointer const_pointer;
262 #ifdef PLF_LIST_ALLOCATOR_TRAITS_SUPPORT
263 typedef typename std::allocator_traits<element_allocator_type>::template rebind_alloc<group> group_allocator_type;
264 typedef typename std::allocator_traits<element_allocator_type>::template rebind_alloc<node> node_allocator_type;
265 typedef typename std::allocator_traits<group_allocator_type>::pointer group_pointer_type;
266 typedef typename std::allocator_traits<node_allocator_type>::pointer node_pointer_type;
267 typedef typename std::allocator_traits<element_allocator_type>::template rebind_alloc<node_pointer_type> node_pointer_allocator_type;
269 typedef typename element_allocator_type::template rebind<group>::other group_allocator_type;
270 typedef typename element_allocator_type::template rebind<node>::other node_allocator_type;
271 typedef typename group_allocator_type::pointer group_pointer_type;
272 typedef typename node_allocator_type::pointer node_pointer_type;
273 typedef typename element_allocator_type::template rebind<node_pointer_type>::other node_pointer_allocator_type;
280 node_pointer_type next, previous;
285 node_base(
const node_pointer_type &n,
const node_pointer_type &p):
291 #ifdef PLF_LIST_MOVE_SEMANTICS_SUPPORT
292 node_base(node_pointer_type &&n, node_pointer_type &&p) PLF_LIST_NOEXCEPT:
294 previous(std::move(p))
301 struct node :
public node_base
303 element_type element;
305 node(
const node_pointer_type next,
const node_pointer_type previous,
const element_type &source):
306 node_base(next, previous),
311 #ifdef PLF_LIST_MOVE_SEMANTICS_SUPPORT
312 node(node_pointer_type &&next, node_pointer_type &&previous, element_type &&source) PLF_LIST_NOEXCEPT:
313 node_base(std::move(next), std::move(previous)),
314 element(std::move(source))
319 #ifdef PLF_LIST_VARIADICS_SUPPORT
320 template<
typename... arguments>
321 node(node_pointer_type
const next, node_pointer_type
const previous, arguments&&... parameters):
322 node_base(next, previous),
323 element(std::forward<arguments>(parameters) ...)
330 struct group :
public node_allocator_type
332 node_pointer_type nodes;
333 node_pointer_type free_list_head;
334 node_pointer_type beyond_end;
335 group_size_type number_of_elements;
338 group() PLF_LIST_NOEXCEPT:
340 free_list_head(NULL),
342 number_of_elements(0)
346 #if defined(PLF_LIST_VARIADICS_SUPPORT) || defined(PLF_LIST_MOVE_SEMANTICS_SUPPORT)
347 group(
const group_size_type group_size, node_pointer_type
const previous = NULL):
348 nodes(PLF_LIST_ALLOCATE_INITIALIZATION(node_allocator_type, group_size, previous)),
349 free_list_head(NULL),
350 beyond_end(nodes + group_size),
351 number_of_elements(0)
355 group(
const group_size_type group_size, node_pointer_type
const previous = NULL) PLF_LIST_NOEXCEPT:
357 free_list_head(previous),
359 number_of_elements(group_size)
363 group(
const group &source):
364 node_allocator_type(source),
365 nodes(PLF_LIST_ALLOCATE_INITIALIZATION(node_allocator_type, source.number_of_elements, source.free_list_head)),
366 free_list_head(NULL),
367 beyond_end(nodes + source.number_of_elements),
368 number_of_elements(0)
373 group & operator = (
const group &source) PLF_LIST_NOEXCEPT
375 nodes = source.nodes;
376 free_list_head = source.free_list_head;
377 beyond_end = source.beyond_end;
378 number_of_elements = source.number_of_elements;
383 #ifdef PLF_LIST_MOVE_SEMANTICS_SUPPORT
384 group(group &&source) PLF_LIST_NOEXCEPT:
385 node_allocator_type(source),
386 nodes(std::move(source.nodes)),
387 free_list_head(std::move(source.free_list_head)),
388 beyond_end(std::move(source.beyond_end)),
389 number_of_elements(source.number_of_elements)
392 source.beyond_end = NULL;
396 group & operator = (group &&source) PLF_LIST_NOEXCEPT
398 nodes = std::move(source.nodes);
399 free_list_head = std::move(source.free_list_head);
400 beyond_end = std::move(source.beyond_end);
401 number_of_elements = std::move(source.number_of_elements);
403 source.beyond_end = NULL;
409 ~group() PLF_LIST_NOEXCEPT
411 PLF_LIST_DEALLOCATE(node_allocator_type, (*
this), nodes,
static_cast<size_type
>(beyond_end - nodes));
418 class group_vector :
private node_pointer_allocator_type
421 group_pointer_type last_endpoint_group, block_pointer, last_searched_group;
428 explicit ebco_pair2(
const size_type number_of_elements) PLF_LIST_NOEXCEPT: capacity(number_of_elements) {};
429 } element_allocator_pair;
434 explicit ebco_pair(
const size_type number_of_groups) PLF_LIST_NOEXCEPT: capacity(number_of_groups) {};
435 } group_allocator_pair;
439 group_vector() PLF_LIST_NOEXCEPT:
440 node_pointer_allocator_type(node_pointer_allocator_type()),
441 last_endpoint_group(NULL),
443 last_searched_group(NULL),
445 element_allocator_pair(0),
446 group_allocator_pair(0)
451 inline PLF_LIST_FORCE_INLINE
void blank() PLF_LIST_NOEXCEPT
453 #ifdef PLF_LIST_TYPE_TRAITS_SUPPORT
454 if PLF_LIST_CONSTEXPR (std::is_trivial<group_pointer_type>::value)
456 std::memset(
static_cast<void *
>(
this), 0,
sizeof(group_vector));
461 last_endpoint_group = NULL;
462 block_pointer = NULL;
463 last_searched_group = NULL;
465 element_allocator_pair.capacity = 0;
466 group_allocator_pair.capacity = 0;
472 #ifdef PLF_LIST_MOVE_SEMANTICS_SUPPORT
473 group_vector(group_vector &&source) PLF_LIST_NOEXCEPT:
474 last_endpoint_group(std::move(source.last_endpoint_group)),
475 block_pointer(std::move(source.block_pointer)),
476 last_searched_group(std::move(source.last_searched_group)),
478 element_allocator_pair(source.element_allocator_pair.capacity),
479 group_allocator_pair(source.group_allocator_pair.capacity)
485 group_vector & operator = (group_vector &&source) PLF_LIST_NOEXCEPT
487 #ifdef PLF_LIST_TYPE_TRAITS_SUPPORT
488 if PLF_LIST_CONSTEXPR (std::is_trivial<group_pointer_type>::value)
490 std::memcpy(
static_cast<void *
>(
this), &source,
sizeof(group_vector));
495 last_endpoint_group = std::move(source.last_endpoint_group);
496 block_pointer = std::move(source.block_pointer);
497 last_searched_group = std::move(source.last_searched_group);
499 element_allocator_pair.capacity = source.element_allocator_pair.capacity;
500 group_allocator_pair.capacity = source.group_allocator_pair.capacity;
510 ~group_vector() PLF_LIST_NOEXCEPT
515 void destroy_all_data(
const node_pointer_type last_endpoint_node) PLF_LIST_NOEXCEPT
517 if (block_pointer == NULL)
522 #ifdef PLF_LIST_TYPE_TRAITS_SUPPORT
523 if PLF_LIST_CONSTEXPR (!std::is_trivially_destructible<element_type>::value || !std::is_trivially_destructible<node_pointer_type>::value)
526 if (last_endpoint_node != NULL)
528 clear(last_endpoint_node);
532 const group_pointer_type end_group = block_pointer + size;
533 for (group_pointer_type current_group = block_pointer; current_group != end_group; ++current_group)
535 PLF_LIST_DESTROY(group_allocator_type, group_allocator_pair, current_group);
538 PLF_LIST_DEALLOCATE(group_allocator_type, group_allocator_pair, block_pointer, group_allocator_pair.capacity);
544 void clear(
const node_pointer_type last_endpoint_node) PLF_LIST_NOEXCEPT
546 for (group_pointer_type current_group = block_pointer; current_group != last_endpoint_group; ++current_group)
548 #ifdef PLF_LIST_TYPE_TRAITS_SUPPORT
549 if PLF_LIST_CONSTEXPR (!std::is_trivially_destructible<element_type>::value || !std::is_trivially_destructible<node_pointer_type>::value)
552 const node_pointer_type end = current_group->beyond_end;
554 if ((end - current_group->nodes) != current_group->number_of_elements)
556 for (node_pointer_type current_node = current_group->nodes; current_node != end; ++current_node)
558 #ifdef PLF_LIST_TYPE_TRAITS_SUPPORT
559 if PLF_LIST_CONSTEXPR (!std::is_trivially_destructible<element_type>::value)
562 if (current_node->next != NULL)
564 PLF_LIST_DESTROY(element_allocator_type, element_allocator_pair, &(current_node->element));
568 #ifdef PLF_LIST_TYPE_TRAITS_SUPPORT
569 if PLF_LIST_CONSTEXPR (!std::is_trivially_destructible<node_pointer_type>::value)
572 PLF_LIST_DESTROY(node_pointer_allocator_type, (*
this), &(current_node->next));
573 PLF_LIST_DESTROY(node_pointer_allocator_type, (*
this), &(current_node->previous));
579 for (node_pointer_type current_node = current_group->nodes; current_node != end; ++current_node)
581 #ifdef PLF_LIST_TYPE_TRAITS_SUPPORT
582 if PLF_LIST_CONSTEXPR (!std::is_trivially_destructible<element_type>::value)
585 PLF_LIST_DESTROY(element_allocator_type, element_allocator_pair, &(current_node->element));
588 #ifdef PLF_LIST_TYPE_TRAITS_SUPPORT
589 if PLF_LIST_CONSTEXPR (!std::is_trivially_destructible<node_pointer_type>::value)
592 PLF_LIST_DESTROY(node_pointer_allocator_type, (*
this), &(current_node->next));
593 PLF_LIST_DESTROY(node_pointer_allocator_type, (*
this), &(current_node->previous));
599 current_group->free_list_head = NULL;
600 current_group->number_of_elements = 0;
603 #ifdef PLF_LIST_TYPE_TRAITS_SUPPORT
604 if PLF_LIST_CONSTEXPR (!std::is_trivially_destructible<element_type>::value || !std::is_trivially_destructible<node_pointer_type>::value)
607 if ((last_endpoint_node - last_endpoint_group->nodes) != last_endpoint_group->number_of_elements)
609 for (node_pointer_type current_node = last_endpoint_group->nodes; current_node != last_endpoint_node; ++current_node)
611 #ifdef PLF_LIST_TYPE_TRAITS_SUPPORT
612 if PLF_LIST_CONSTEXPR (!std::is_trivially_destructible<element_type>::value)
615 if (current_node->next != NULL)
617 PLF_LIST_DESTROY(element_allocator_type, element_allocator_pair, &(current_node->element));
621 #ifdef PLF_LIST_TYPE_TRAITS_SUPPORT
622 if PLF_LIST_CONSTEXPR (!std::is_trivially_destructible<node_pointer_type>::value)
625 PLF_LIST_DESTROY(node_pointer_allocator_type, (*
this), &(current_node->next));
626 PLF_LIST_DESTROY(node_pointer_allocator_type, (*
this), &(current_node->previous));
632 for (node_pointer_type current_node = last_endpoint_group->nodes; current_node != last_endpoint_node; ++current_node)
634 #ifdef PLF_LIST_TYPE_TRAITS_SUPPORT
635 if PLF_LIST_CONSTEXPR (!std::is_trivially_destructible<element_type>::value)
638 PLF_LIST_DESTROY(element_allocator_type, element_allocator_pair, &(current_node->element));
641 #ifdef PLF_LIST_TYPE_TRAITS_SUPPORT
642 if PLF_LIST_CONSTEXPR (!std::is_trivially_destructible<node_pointer_type>::value)
645 PLF_LIST_DESTROY(node_pointer_allocator_type, (*
this), &(current_node->next));
646 PLF_LIST_DESTROY(node_pointer_allocator_type, (*
this), &(current_node->previous));
652 last_endpoint_group->free_list_head = NULL;
653 last_endpoint_group->number_of_elements = 0;
654 last_searched_group = last_endpoint_group = block_pointer;
659 void expand_capacity(
const size_type new_capacity)
661 group_pointer_type
const old_block = block_pointer;
662 block_pointer = PLF_LIST_ALLOCATE(group_allocator_type, group_allocator_pair, new_capacity, 0);
664 #ifdef PLF_LIST_TYPE_TRAITS_SUPPORT
665 if PLF_LIST_CONSTEXPR (std::is_trivially_copyable<node_pointer_type>::value && std::is_trivially_destructible<node_pointer_type>::value)
667 std::memcpy(
static_cast<void *
>(&*block_pointer),
static_cast<void *
>(&*old_block),
sizeof(group) * size);
669 #ifdef PLF_LIST_MOVE_SEMANTICS_SUPPORT
670 else if PLF_LIST_CONSTEXPR (std::is_move_constructible<node_pointer_type>::value)
672 std::uninitialized_copy(std::make_move_iterator(old_block), std::make_move_iterator(old_block + size), block_pointer);
679 const group_pointer_type beyond_end = old_block + size;
680 group_pointer_type current_new_group = block_pointer;
682 for (group_pointer_type current_group = old_block; current_group != beyond_end; ++current_group)
684 *(current_new_group++) = *(current_group);
686 current_group->nodes = NULL;
687 current_group->beyond_end = NULL;
688 PLF_LIST_DESTROY(group_allocator_type, group_allocator_pair, current_group);
692 last_searched_group = block_pointer + (last_searched_group - old_block);
693 PLF_LIST_DEALLOCATE(group_allocator_type, group_allocator_pair, old_block, group_allocator_pair.capacity);
694 group_allocator_pair.capacity = new_capacity;
699 void add_new(
const group_size_type group_size)
701 if (group_allocator_pair.capacity == size)
703 expand_capacity(group_allocator_pair.capacity * 2);
706 last_endpoint_group = block_pointer + size - 1;
708 #ifdef PLF_LIST_VARIADICS_SUPPORT
709 PLF_LIST_CONSTRUCT(group_allocator_type, group_allocator_pair, last_endpoint_group + 1, group_size, last_endpoint_group->nodes);
711 PLF_LIST_CONSTRUCT(group_allocator_type, group_allocator_pair, last_endpoint_group + 1, group(group_size, last_endpoint_group->nodes));
714 ++last_endpoint_group;
715 element_allocator_pair.capacity += group_size;
721 void initialize(
const group_size_type group_size)
723 last_endpoint_group = block_pointer = last_searched_group = PLF_LIST_ALLOCATE(group_allocator_type, group_allocator_pair, 1, 0);
724 group_allocator_pair.capacity = 1;
726 #ifdef PLF_LIST_VARIADICS_SUPPORT
727 PLF_LIST_CONSTRUCT(group_allocator_type, group_allocator_pair, last_endpoint_group, group_size);
729 PLF_LIST_CONSTRUCT(group_allocator_type, group_allocator_pair, last_endpoint_group, group(group_size));
733 element_allocator_pair.capacity = group_size;
738 void remove(group_pointer_type
const group_to_erase) PLF_LIST_NOEXCEPT
740 if (last_searched_group >= group_to_erase && last_searched_group != block_pointer)
742 --last_searched_group;
745 element_allocator_pair.capacity -=
static_cast<size_type
>(group_to_erase->beyond_end - group_to_erase->nodes);
747 PLF_LIST_DESTROY(group_allocator_type, group_allocator_pair, group_to_erase);
749 #ifdef PLF_LIST_TYPE_TRAITS_SUPPORT
750 if PLF_LIST_CONSTEXPR (std::is_trivially_copyable<node_pointer_type>::value && std::is_trivially_destructible<node_pointer_type>::value)
752 std::memmove(
static_cast<void *
>(&*group_to_erase),
static_cast<void *
>(&*group_to_erase + 1),
sizeof(group) * (--size -
static_cast<size_type
>(&*group_to_erase - &*block_pointer)));
754 #ifdef PLF_LIST_MOVE_SEMANTICS_SUPPORT
755 else if PLF_LIST_CONSTEXPR (std::is_move_constructible<node_pointer_type>::value)
757 std::move(group_to_erase + 1, block_pointer + size--, group_to_erase);
763 group_pointer_type back = block_pointer + size--;
764 std::copy(group_to_erase + 1, back--, group_to_erase);
767 back->beyond_end = NULL;
768 PLF_LIST_DESTROY(group_allocator_type, group_allocator_pair, back);
774 void move_to_back(group_pointer_type
const group_to_erase)
776 if (last_searched_group >= group_to_erase && last_searched_group != block_pointer)
778 --last_searched_group;
781 group *temp_group = PLF_LIST_ALLOCATE(group_allocator_type, group_allocator_pair, 1, NULL);
783 #ifdef PLF_LIST_TYPE_TRAITS_SUPPORT
784 if PLF_LIST_CONSTEXPR (std::is_trivially_copyable<node_pointer_type>::value && std::is_trivially_destructible<node_pointer_type>::value)
786 std::memcpy(
static_cast<void *
>(&*temp_group),
static_cast<void *
>(&*group_to_erase),
sizeof(group));
787 std::memmove(
static_cast<void *
>(&*group_to_erase),
static_cast<void *
>(&*group_to_erase + 1),
sizeof(group) * ((size - 1) -
static_cast<size_type
>(&*group_to_erase - &*block_pointer)));
788 std::memcpy(
static_cast<void *
>(&*(block_pointer + size - 1)),
static_cast<void *
>(&*temp_group),
sizeof(group));
790 #ifdef PLF_LIST_MOVE_SEMANTICS_SUPPORT
791 else if PLF_LIST_CONSTEXPR (std::is_move_constructible<node_pointer_type>::value)
793 PLF_LIST_CONSTRUCT(group_allocator_type, group_allocator_pair, temp_group, std::move(*group_to_erase));
794 std::move(group_to_erase + 1, block_pointer + size, group_to_erase);
795 *(block_pointer + size - 1) = std::move(*temp_group);
797 if PLF_LIST_CONSTEXPR (!std::is_trivially_destructible<node_pointer_type>::value)
799 PLF_LIST_DESTROY(group_allocator_type, group_allocator_pair, temp_group);
806 PLF_LIST_CONSTRUCT(group_allocator_type, group_allocator_pair, temp_group, group());
808 *temp_group = *group_to_erase;
809 std::copy(group_to_erase + 1, block_pointer + size, group_to_erase);
810 *(block_pointer + --size) = *temp_group;
812 temp_group->nodes = NULL;
813 PLF_LIST_DESTROY(group_allocator_type, group_allocator_pair, temp_group);
816 PLF_LIST_DEALLOCATE(group_allocator_type, group_allocator_pair, temp_group, 1);
821 group_pointer_type get_nearest_freelist_group(
const node_pointer_type location_node) PLF_LIST_NOEXCEPT
823 const group_pointer_type beyond_end_group = last_endpoint_group + 1;
824 group_pointer_type left = last_searched_group - 1, right = last_searched_group + 1, freelist_group = NULL;
825 bool right_not_beyond_back = (right < beyond_end_group);
826 bool left_not_beyond_front = (left >= block_pointer);
829 if (location_node >= last_searched_group->nodes && location_node < last_searched_group->beyond_end)
831 if (last_searched_group->free_list_head != NULL)
833 return last_searched_group;
838 group_pointer_type closest_freelist_left = (last_searched_group->free_list_head == NULL) ? NULL : last_searched_group, closest_freelist_right = (last_searched_group->free_list_head == NULL) ? NULL : last_searched_group;
842 if (right_not_beyond_back)
844 if ((location_node < right->beyond_end) && (location_node >= right->nodes))
846 if (right->free_list_head != NULL)
848 last_searched_group = right;
852 difference_type left_distance;
854 if (closest_freelist_right != NULL)
856 last_searched_group = right;
857 left_distance = right - closest_freelist_right;
859 if (left_distance <= 2)
861 return closest_freelist_right;
864 freelist_group = closest_freelist_right;
868 last_searched_group = right;
869 left_distance = right - left;
874 const group_pointer_type end_group = (((right + left_distance) > beyond_end_group) ? beyond_end_group : (right + left_distance - 1));
876 while (++right != end_group)
878 if (right->free_list_head != NULL)
884 if (freelist_group != NULL)
886 return freelist_group;
889 right_not_beyond_back = (right < beyond_end_group);
893 if (right->free_list_head != NULL)
895 if ((closest_freelist_right == NULL) & (closest_freelist_left == NULL))
897 closest_freelist_left = right;
900 closest_freelist_right = right;
903 right_not_beyond_back = (++right < beyond_end_group);
907 if (left_not_beyond_front)
909 if ((location_node >= left->nodes) && (location_node < left->beyond_end))
911 if (left->free_list_head != NULL)
913 last_searched_group = left;
917 difference_type right_distance;
919 if (closest_freelist_left != NULL)
921 last_searched_group = left;
922 right_distance = closest_freelist_left - left;
924 if (right_distance <= 2)
926 return closest_freelist_left;
929 freelist_group = closest_freelist_left;
933 last_searched_group = left;
934 right_distance = right - left;
938 const group_pointer_type end_group = (((left - right_distance) < block_pointer) ? block_pointer - 1 : (left - right_distance) + 1);
940 while (--left != end_group)
942 if (left->free_list_head != NULL)
948 if (freelist_group != NULL)
950 return freelist_group;
953 left_not_beyond_front = (left >= block_pointer);
957 if (left->free_list_head != NULL)
959 if ((closest_freelist_left == NULL) & (closest_freelist_right == NULL))
961 closest_freelist_right = left;
964 closest_freelist_left = left;
967 left_not_beyond_front = (--left >= block_pointer);
976 if (right_not_beyond_back)
978 if (right->free_list_head != NULL)
983 right_not_beyond_back = (++right < beyond_end_group);
986 if (left_not_beyond_front)
988 if (left->free_list_head != NULL)
993 left_not_beyond_front = (--left >= block_pointer);
1002 void swap(group_vector &source) PLF_LIST_NOEXCEPT_SWAP(group_allocator_type)
1004 #ifdef PLF_LIST_TYPE_TRAITS_SUPPORT
1005 if PLF_LIST_CONSTEXPR (std::is_trivial<group_pointer_type>::value)
1007 char temp[
sizeof(group_vector)];
1008 std::memcpy(
static_cast<void *
>(&temp),
static_cast<void *
>(
this),
sizeof(group_vector));
1009 std::memcpy(
static_cast<void *
>(
this),
static_cast<void *
>(&source),
sizeof(group_vector));
1010 std::memcpy(
static_cast<void *
>(&source),
static_cast<void *
>(&temp),
sizeof(group_vector));
1015 const group_pointer_type swap_last_endpoint_group = last_endpoint_group, swap_block_pointer = block_pointer, swap_last_searched_group = last_searched_group;
1016 const size_type swap_size = size, swap_element_capacity = element_allocator_pair.capacity, swap_capacity = group_allocator_pair.capacity;
1018 last_endpoint_group = source.last_endpoint_group;
1019 block_pointer = source.block_pointer;
1020 last_searched_group = source.last_searched_group;
1022 element_allocator_pair.capacity = source.element_allocator_pair.capacity;
1023 group_allocator_pair.capacity = source.group_allocator_pair.capacity;
1025 source.last_endpoint_group = swap_last_endpoint_group;
1026 source.block_pointer = swap_block_pointer;
1027 source.last_searched_group = swap_last_searched_group;
1028 source.size = swap_size;
1029 source.element_allocator_pair.capacity = swap_element_capacity;
1030 source.group_allocator_pair.capacity = swap_capacity;
1036 void trim_trailing_groups() PLF_LIST_NOEXCEPT
1038 const group_pointer_type beyond_last = block_pointer + size;
1040 for (group_pointer_type current_group = last_endpoint_group + 1; current_group != beyond_last; ++current_group)
1042 element_allocator_pair.capacity -=
static_cast<size_type
>(current_group->beyond_end - current_group->nodes);
1043 PLF_LIST_DESTROY(group_allocator_type, group_allocator_pair, current_group);
1046 size -=
static_cast<size_type
>(beyond_last - (last_endpoint_group + 1));
1051 void append(group_vector &source)
1053 source.trim_trailing_groups();
1054 trim_trailing_groups();
1056 if (size + source.size > group_allocator_pair.capacity)
1058 expand_capacity(size + source.size);
1061 #ifdef PLF_LIST_TYPE_TRAITS_SUPPORT
1062 if PLF_LIST_CONSTEXPR (std::is_trivially_copyable<node_pointer_type>::value && std::is_trivially_destructible<node_pointer_type>::value)
1064 std::memcpy(
static_cast<void *
>(&*block_pointer + size),
static_cast<void *
>(&*source.block_pointer),
sizeof(group) * source.size);
1066 #ifdef PLF_LIST_MOVE_SEMANTICS_SUPPORT
1067 else if PLF_LIST_CONSTEXPR (std::is_move_constructible<node_pointer_type>::value)
1069 std::uninitialized_copy(std::make_move_iterator(source.block_pointer), std::make_move_iterator(source.block_pointer + source.size), block_pointer + size);
1075 group_pointer_type current_new_group = block_pointer + size;
1076 const group_pointer_type beyond_end_source = source.block_pointer + source.size;
1078 for (group_pointer_type current_group = source.block_pointer; current_group != beyond_end_source; ++current_group)
1080 *(current_new_group++) = *(current_group);
1082 current_group->nodes = NULL;
1083 current_group->beyond_end = NULL;
1084 PLF_LIST_DESTROY(group_allocator_type, source.group_allocator_pair, current_group);
1088 PLF_LIST_DEALLOCATE(group_allocator_type, source.group_allocator_pair, source.block_pointer, source.group_allocator_pair.capacity);
1089 size += source.size;
1090 last_endpoint_group = block_pointer + size - 1;
1091 element_allocator_pair.capacity += source.element_allocator_pair.capacity;
1099 template <
bool flag,
class IsTrue,
class IsFalse>
struct choose;
1101 template <
class IsTrue,
class IsFalse>
struct choose<true, IsTrue, IsFalse>
1103 typedef IsTrue type;
1106 template <
class IsTrue,
class IsFalse>
struct choose<false, IsTrue, IsFalse>
1108 typedef IsFalse type;
1117 node_pointer_type node_pointer;
1120 typedef std::bidirectional_iterator_tag iterator_category;
1121 typedef typename list::value_type value_type;
1122 typedef typename list::difference_type difference_type;
1123 typedef typename choose<is_const, typename list::const_pointer, typename list::pointer>::type pointer;
1124 typedef typename choose<is_const, typename list::const_reference, typename list::reference>::type reference;
1128 auto getNodePointer()
const {
1129 return node_pointer;
1132 inline PLF_LIST_FORCE_INLINE
bool operator == (
const list_iterator rh)
const PLF_LIST_NOEXCEPT
1134 return (node_pointer == rh.node_pointer);
1141 return (node_pointer == rh.node_pointer);
1146 inline PLF_LIST_FORCE_INLINE
bool operator != (
const list_iterator rh)
const PLF_LIST_NOEXCEPT
1148 return (node_pointer != rh.node_pointer);
1155 return (node_pointer != rh.node_pointer);
1160 inline PLF_LIST_FORCE_INLINE reference operator * ()
const
1162 return node_pointer->element;
1167 inline PLF_LIST_FORCE_INLINE pointer operator -> ()
const
1169 return &(node_pointer->element);
1174 inline PLF_LIST_FORCE_INLINE
list_iterator & operator ++ () PLF_LIST_NOEXCEPT
1176 assert(node_pointer != NULL);
1177 node_pointer = node_pointer->next;
1192 inline PLF_LIST_FORCE_INLINE
list_iterator & operator -- () PLF_LIST_NOEXCEPT
1194 assert(node_pointer != NULL);
1195 node_pointer = node_pointer->previous;
1212 node_pointer = rh.node_pointer;
1220 node_pointer = rh.node_pointer;
1226 #ifdef PLF_LIST_MOVE_SEMANTICS_SUPPORT
1229 assert (&rh !=
this);
1230 node_pointer = std::move(rh.node_pointer);
1237 node_pointer = std::move(rh.node_pointer);
1250 #ifdef PLF_LIST_MOVE_SEMANTICS_SUPPORT
1258 list_iterator (
const node_pointer_type node_p) PLF_LIST_NOEXCEPT: node_pointer(node_p) {}
1267 node_pointer_type node_pointer;
1270 typedef std::bidirectional_iterator_tag iterator_category;
1271 typedef typename list::value_type value_type;
1272 typedef typename list::difference_type difference_type;
1273 typedef typename choose<is_const, typename list::const_pointer, typename list::pointer>::type pointer;
1274 typedef typename choose<is_const, typename list::const_reference, typename list::reference>::type reference;
1279 inline PLF_LIST_FORCE_INLINE
bool operator == (
const list_reverse_iterator rh)
const PLF_LIST_NOEXCEPT
1281 return (node_pointer == rh.node_pointer);
1288 return (node_pointer == rh.node_pointer);
1293 inline PLF_LIST_FORCE_INLINE
bool operator != (
const list_reverse_iterator rh)
const PLF_LIST_NOEXCEPT
1295 return (node_pointer != rh.node_pointer);
1302 return (node_pointer != rh.node_pointer);
1307 inline PLF_LIST_FORCE_INLINE reference operator * ()
const
1309 return node_pointer->element;
1314 inline PLF_LIST_FORCE_INLINE pointer operator -> ()
const
1316 return &(node_pointer->element);
1323 assert(node_pointer != NULL);
1324 node_pointer = node_pointer->previous;
1341 assert(node_pointer != NULL);
1342 node_pointer = node_pointer->next;
1359 node_pointer = rh.node_pointer;
1367 node_pointer = rh.node_pointer;
1373 #ifdef PLF_LIST_MOVE_SEMANTICS_SUPPORT
1376 assert (&rh !=
this);
1377 node_pointer = std::move(rh.node_pointer);
1384 node_pointer = std::move(rh.node_pointer);
1402 #ifdef PLF_LIST_MOVE_SEMANTICS_SUPPORT
1404 node_pointer(std::move(source.node_pointer))
1406 assert(&source !=
this);
1422 template <
bool condition,
class T =
void>
1423 struct plf_enable_if_c
1429 struct plf_enable_if_c<false, T>
1434 group_vector groups;
1437 node_pointer_type last_endpoint;
1441 iterator end_iterator, begin_iterator;
1445 struct ebco_pair1 : node_pointer_allocator_type
1447 size_type total_number_of_elements;
1448 explicit ebco_pair1(
const size_type total_num_elements) PLF_LIST_NOEXCEPT: total_number_of_elements(total_num_elements) {}
1449 } node_pointer_allocator_pair;
1451 struct ebco_pair2 : node_allocator_type
1453 size_type number_of_erased_nodes;
1454 explicit ebco_pair2(
const size_type num_erased_nodes) PLF_LIST_NOEXCEPT: number_of_erased_nodes(num_erased_nodes) {}
1455 } node_allocator_pair;
1463 list() PLF_LIST_NOEXCEPT:
1464 element_allocator_type(element_allocator_type()),
1465 end_node(reinterpret_cast<node_pointer_type>(&end_node), reinterpret_cast<node_pointer_type>(&end_node)),
1466 last_endpoint(NULL),
1467 end_iterator(reinterpret_cast<node_pointer_type>(&end_node)),
1468 begin_iterator(reinterpret_cast<node_pointer_type>(&end_node)),
1469 node_pointer_allocator_pair(0),
1470 node_allocator_pair(0)
1477 explicit list(
const element_allocator_type &alloc):
1478 element_allocator_type(alloc),
1479 end_node(reinterpret_cast<node_pointer_type>(&end_node), reinterpret_cast<node_pointer_type>(&end_node)),
1480 last_endpoint(NULL),
1481 end_iterator(reinterpret_cast<node_pointer_type>(&end_node)),
1482 begin_iterator(reinterpret_cast<node_pointer_type>(&end_node)),
1483 node_pointer_allocator_pair(0),
1484 node_allocator_pair(0)
1491 list(
const list &source):
1492 element_allocator_type(source),
1493 end_node(reinterpret_cast<node_pointer_type>(&end_node), reinterpret_cast<node_pointer_type>(&end_node)),
1494 last_endpoint(NULL),
1495 end_iterator(reinterpret_cast<node_pointer_type>(&end_node)),
1496 begin_iterator(reinterpret_cast<node_pointer_type>(&end_node)),
1497 node_pointer_allocator_pair(0),
1498 node_allocator_pair(0)
1500 reserve(source.node_pointer_allocator_pair.total_number_of_elements);
1501 insert(end_iterator, source.begin_iterator, source.end_iterator);
1508 list(
const list &source,
const allocator_type &alloc):
1509 element_allocator_type(alloc),
1510 end_node(reinterpret_cast<node_pointer_type>(&end_node), reinterpret_cast<node_pointer_type>(&end_node)),
1511 last_endpoint(NULL),
1512 end_iterator(reinterpret_cast<node_pointer_type>(&end_node)),
1513 begin_iterator(reinterpret_cast<node_pointer_type>(&end_node)),
1514 node_pointer_allocator_pair(0),
1515 node_allocator_pair(0)
1517 reserve(source.node_pointer_allocator_pair.total_number_of_elements);
1518 insert(end_iterator, source.begin_iterator, source.end_iterator);
1523 #ifdef PLF_LIST_MOVE_SEMANTICS_SUPPORT
1526 list(list &&source) PLF_LIST_NOEXCEPT:
1527 element_allocator_type(source),
1528 groups(std::move(source.groups)),
1529 end_node(std::move(source.end_node)),
1530 last_endpoint(std::move(source.last_endpoint)),
1531 end_iterator(
reinterpret_cast<node_pointer_type
>(&end_node)),
1532 begin_iterator((source.begin_iterator.node_pointer == source.end_iterator.node_pointer) ?
reinterpret_cast<node_pointer_type
>(&end_node) : std::move(source.begin_iterator)),
1533 node_pointer_allocator_pair(source.node_pointer_allocator_pair.total_number_of_elements),
1534 node_allocator_pair(source.node_allocator_pair.number_of_erased_nodes)
1536 assert(&source !=
this);
1537 end_node.previous->next = begin_iterator.node_pointer->previous = end_iterator.node_pointer;
1538 source.groups.blank();
1546 list(list &&source,
const allocator_type &alloc):
1547 element_allocator_type(alloc),
1548 groups(std::move(source.groups)),
1549 end_node(std::move(source.end_node)),
1550 last_endpoint(std::move(source.last_endpoint)),
1551 end_iterator(reinterpret_cast<node_pointer_type>(&end_node)),
1552 begin_iterator((source.begin_iterator.node_pointer == source.end_iterator.node_pointer) ? reinterpret_cast<node_pointer_type>(&end_node) : std::move(source.begin_iterator)),
1553 node_pointer_allocator_pair(source.node_pointer_allocator_pair.total_number_of_elements),
1554 node_allocator_pair(source.node_allocator_pair.number_of_erased_nodes)
1556 assert(&source !=
this);
1557 end_node.previous->next = begin_iterator.node_pointer->previous = end_iterator.node_pointer;
1558 source.groups.blank();
1567 list(
const size_type fill_number,
const element_type &element,
const element_allocator_type &alloc = element_allocator_type()):
1568 element_allocator_type(alloc),
1569 end_node(reinterpret_cast<node_pointer_type>(&end_node), reinterpret_cast<node_pointer_type>(&end_node)),
1570 last_endpoint(NULL),
1571 end_iterator(reinterpret_cast<node_pointer_type>(&end_node)),
1572 begin_iterator(reinterpret_cast<node_pointer_type>(&end_node)),
1573 node_pointer_allocator_pair(0),
1574 node_allocator_pair(0)
1576 reserve(fill_number);
1577 insert(end_iterator, fill_number, element);
1584 template<
typename iterator_type>
1585 list(
const typename plf_enable_if_c<!std::numeric_limits<iterator_type>::is_integer, iterator_type>::type &first,
const iterator_type &last,
const element_allocator_type &alloc = element_allocator_type()):
1586 element_allocator_type(alloc),
1587 end_node(reinterpret_cast<node_pointer_type>(&end_node), reinterpret_cast<node_pointer_type>(&end_node)),
1588 last_endpoint(NULL),
1589 end_iterator(reinterpret_cast<node_pointer_type>(&end_node)),
1590 begin_iterator(reinterpret_cast<node_pointer_type>(&end_node)),
1591 node_pointer_allocator_pair(0),
1592 node_allocator_pair(0)
1594 insert<iterator_type>(end_iterator, first, last);
1601 #ifdef PLF_LIST_INITIALIZER_LIST_SUPPORT
1602 list(
const std::initializer_list<element_type> &element_list,
const element_allocator_type &alloc = element_allocator_type()):
1603 element_allocator_type(alloc),
1604 end_node(reinterpret_cast<node_pointer_type>(&end_node), reinterpret_cast<node_pointer_type>(&end_node)),
1605 last_endpoint(NULL),
1606 end_iterator(reinterpret_cast<node_pointer_type>(&end_node)),
1607 begin_iterator(reinterpret_cast<node_pointer_type>(&end_node)),
1608 node_pointer_allocator_pair(0),
1609 node_allocator_pair(0)
1611 reserve(element_list.size());
1612 insert(end_iterator, element_list);
1619 ~list() PLF_LIST_NOEXCEPT
1621 groups.destroy_all_data(last_endpoint);
1626 inline iterator begin() PLF_LIST_NOEXCEPT
1628 return begin_iterator;
1633 inline const_iterator begin() const PLF_LIST_NOEXCEPT
1635 return begin_iterator;
1640 inline iterator end() PLF_LIST_NOEXCEPT
1642 return end_iterator;
1647 inline const_iterator end() const PLF_LIST_NOEXCEPT
1649 return end_iterator;
1654 inline const_iterator cbegin() const PLF_LIST_NOEXCEPT
1656 return const_iterator(begin_iterator.node_pointer);
1661 inline const_iterator cend() const PLF_LIST_NOEXCEPT
1663 return const_iterator(end_iterator.node_pointer);
1668 inline reverse_iterator rbegin() const PLF_LIST_NOEXCEPT
1670 return reverse_iterator(end_node.previous);
1675 inline reverse_iterator rend() const PLF_LIST_NOEXCEPT
1677 return reverse_iterator(end_iterator.node_pointer);
1682 inline const_reverse_iterator crbegin() const PLF_LIST_NOEXCEPT
1684 return const_reverse_iterator(end_node.previous);
1689 inline const_reverse_iterator crend() const PLF_LIST_NOEXCEPT
1691 return const_reverse_iterator(end_iterator.node_pointer);
1696 inline reference front()
1698 assert(begin_iterator.node_pointer != &end_node);
1699 return begin_iterator.node_pointer->element;
1704 inline const_reference front()
const
1706 assert(begin_iterator.node_pointer != &end_node);
1707 return begin_iterator.node_pointer->element;
1712 inline reference back()
1714 assert(end_node.previous != &end_node);
1715 return end_node.previous->element;
1720 inline const_reference back()
const
1722 assert(end_node.previous != &end_node);
1723 return end_node.previous->element;
1728 void clear() PLF_LIST_NOEXCEPT
1730 if (last_endpoint == NULL)
1735 if (node_pointer_allocator_pair.total_number_of_elements != 0)
1737 groups.clear(last_endpoint);
1740 end_node.next =
reinterpret_cast<node_pointer_type
>(&end_node);
1741 end_node.previous =
reinterpret_cast<node_pointer_type
>(&end_node);
1742 last_endpoint = NULL;
1743 begin_iterator.node_pointer = end_iterator.node_pointer;
1744 node_pointer_allocator_pair.total_number_of_elements = 0;
1745 node_allocator_pair.number_of_erased_nodes = 0;
1753 void reset() PLF_LIST_NOEXCEPT
1755 groups.destroy_all_data(last_endpoint);
1756 last_endpoint = NULL;
1757 end_node.next =
reinterpret_cast<node_pointer_type
>(&end_node);
1758 end_node.previous =
reinterpret_cast<node_pointer_type
>(&end_node);
1759 begin_iterator.node_pointer = end_iterator.node_pointer;
1760 node_pointer_allocator_pair.total_number_of_elements = 0;
1761 node_allocator_pair.number_of_erased_nodes = 0;
1766 inline void add_group_if_necessary()
1768 if (last_endpoint == groups.last_endpoint_group->beyond_end)
1770 if (
static_cast<size_type
>(groups.last_endpoint_group - groups.block_pointer) == groups.size - 1)
1772 groups.add_new((node_pointer_allocator_pair.total_number_of_elements < PLF_LIST_BLOCK_MAX) ?
static_cast<group_size_type
>(node_pointer_allocator_pair.total_number_of_elements) : PLF_LIST_BLOCK_MAX);
1776 ++groups.last_endpoint_group;
1779 last_endpoint = groups.last_endpoint_group->nodes;
1785 inline void update_sizes_and_iterators(
const const_iterator it)
1787 ++(groups.last_endpoint_group->number_of_elements);
1788 ++node_pointer_allocator_pair.total_number_of_elements;
1790 if (it.node_pointer == begin_iterator.node_pointer)
1792 begin_iterator.node_pointer = last_endpoint;
1795 it.node_pointer->previous->next = last_endpoint;
1796 it.node_pointer->previous = last_endpoint;
1801 inline void insert_initialize()
1803 if (groups.block_pointer == NULL)
1805 groups.initialize(PLF_LIST_BLOCK_MIN);
1808 groups.last_endpoint_group->number_of_elements = 1;
1809 end_node.next = end_node.previous = last_endpoint = begin_iterator.node_pointer = groups.last_endpoint_group->nodes;
1810 node_pointer_allocator_pair.total_number_of_elements = 1;
1818 iterator insert(
const const_iterator it,
const element_type &element)
1820 if (last_endpoint != NULL)
1822 if (node_allocator_pair.number_of_erased_nodes == 0)
1824 add_group_if_necessary();
1826 #ifdef PLF_LIST_VARIADICS_SUPPORT
1827 PLF_LIST_CONSTRUCT(node_allocator_type, node_allocator_pair, last_endpoint, it.node_pointer, it.node_pointer->previous, element);
1829 PLF_LIST_CONSTRUCT(node_allocator_type, node_allocator_pair, last_endpoint, node(it.node_pointer, it.node_pointer->previous, element));
1832 update_sizes_and_iterators(it);
1833 return iterator(last_endpoint++);
1837 group_pointer_type
const node_group = groups.get_nearest_freelist_group((it.node_pointer != end_iterator.node_pointer) ? it.node_pointer : end_node.previous);
1838 node_pointer_type
const selected_node = node_group->free_list_head;
1839 const node_pointer_type previous = node_group->free_list_head->previous;
1841 #ifdef PLF_LIST_VARIADICS_SUPPORT
1842 PLF_LIST_CONSTRUCT(node_allocator_type, node_allocator_pair, selected_node, it.node_pointer, it.node_pointer->previous, element);
1844 PLF_LIST_CONSTRUCT(node_allocator_type, node_allocator_pair, selected_node, node(it.node_pointer, it.node_pointer->previous, element));
1847 node_group->free_list_head = previous;
1848 ++(node_group->number_of_elements);
1849 ++node_pointer_allocator_pair.total_number_of_elements;
1850 --node_allocator_pair.number_of_erased_nodes;
1852 it.node_pointer->previous->next = selected_node;
1853 it.node_pointer->previous = selected_node;
1855 if (it.node_pointer == begin_iterator.node_pointer)
1857 begin_iterator.node_pointer = selected_node;
1860 return iterator(selected_node);
1865 insert_initialize();
1867 #ifdef PLF_LIST_TYPE_TRAITS_SUPPORT
1868 if PLF_LIST_CONSTEXPR (std::is_nothrow_copy_constructible<node>::value)
1870 #ifdef PLF_LIST_VARIADICS_SUPPORT
1871 PLF_LIST_CONSTRUCT(node_allocator_type, node_allocator_pair, last_endpoint++, end_iterator.node_pointer, end_iterator.node_pointer, element);
1873 PLF_LIST_CONSTRUCT(node_allocator_type, node_allocator_pair, last_endpoint++, node(end_iterator.node_pointer, end_iterator.node_pointer, element));
1881 #ifdef PLF_LIST_VARIADICS_SUPPORT
1882 PLF_LIST_CONSTRUCT(node_allocator_type, node_allocator_pair, last_endpoint++, end_iterator.node_pointer, end_iterator.node_pointer, element);
1884 PLF_LIST_CONSTRUCT(node_allocator_type, node_allocator_pair, last_endpoint++, node(end_iterator.node_pointer, end_iterator.node_pointer, element));
1894 return begin_iterator;
1900 inline PLF_LIST_FORCE_INLINE
void push_back(
const element_type &element)
1902 insert(end_iterator, element);
1907 inline PLF_LIST_FORCE_INLINE
void push_front(
const element_type &element)
1909 insert(begin_iterator, element);
1914 #ifdef PLF_LIST_MOVE_SEMANTICS_SUPPORT
1915 iterator insert(
const const_iterator it, element_type &&element)
1917 if (last_endpoint != NULL)
1919 if (node_allocator_pair.number_of_erased_nodes == 0)
1921 add_group_if_necessary();
1923 #ifdef PLF_LIST_VARIADICS_SUPPORT
1924 PLF_LIST_CONSTRUCT(node_allocator_type, node_allocator_pair, last_endpoint, it.node_pointer, it.node_pointer->previous, std::move(element));
1926 PLF_LIST_CONSTRUCT(node_allocator_type, node_allocator_pair, last_endpoint, node(it.node_pointer, it.node_pointer->previous, std::move(element)));
1929 update_sizes_and_iterators(it);
1930 return iterator(last_endpoint++);
1934 group_pointer_type
const node_group = groups.get_nearest_freelist_group((it.node_pointer != end_iterator.node_pointer) ? it.node_pointer : end_node.previous);
1935 node_pointer_type
const selected_node = node_group->free_list_head;
1936 const node_pointer_type previous = node_group->free_list_head->previous;
1938 #ifdef PLF_LIST_VARIADICS_SUPPORT
1939 PLF_LIST_CONSTRUCT(node_allocator_type, node_allocator_pair, selected_node, it.node_pointer, it.node_pointer->previous, std::move(element));
1941 PLF_LIST_CONSTRUCT(node_allocator_type, node_allocator_pair, selected_node, node(it.node_pointer, it.node_pointer->previous, std::move(element)));
1944 node_group->free_list_head = previous;
1945 ++(node_group->number_of_elements);
1946 ++node_pointer_allocator_pair.total_number_of_elements;
1947 --node_allocator_pair.number_of_erased_nodes;
1949 it.node_pointer->previous->next = selected_node;
1950 it.node_pointer->previous = selected_node;
1952 if (it.node_pointer == begin_iterator.node_pointer)
1954 begin_iterator.node_pointer = selected_node;
1957 return iterator(selected_node);
1962 insert_initialize();
1964 #ifdef PLF_LIST_TYPE_TRAITS_SUPPORT
1965 if PLF_LIST_CONSTEXPR (std::is_nothrow_move_constructible<node>::value)
1967 #ifdef PLF_LIST_VARIADICS_SUPPORT
1968 PLF_LIST_CONSTRUCT(node_allocator_type, node_allocator_pair, last_endpoint++, end_iterator.node_pointer, end_iterator.node_pointer, std::move(element));
1970 PLF_LIST_CONSTRUCT(node_allocator_type, node_allocator_pair, last_endpoint++, node(end_iterator.node_pointer, end_iterator.node_pointer, std::move(element)));
1978 #ifdef PLF_LIST_VARIADICS_SUPPORT
1979 PLF_LIST_CONSTRUCT(node_allocator_type, node_allocator_pair, last_endpoint++, end_iterator.node_pointer, end_iterator.node_pointer, std::move(element));
1981 PLF_LIST_CONSTRUCT(node_allocator_type, node_allocator_pair, last_endpoint++, node(end_iterator.node_pointer, end_iterator.node_pointer, std::move(element)));
1991 return begin_iterator;
1997 inline PLF_LIST_FORCE_INLINE
void push_back(element_type &&element)
1999 insert(end_iterator, std::move(element));
2004 inline PLF_LIST_FORCE_INLINE
void push_front(element_type &&element)
2006 insert(begin_iterator, std::move(element));
2013 #ifdef PLF_LIST_VARIADICS_SUPPORT
2014 template<
typename... arguments>
2015 iterator emplace(
const const_iterator it, arguments &&... parameters)
2017 if (last_endpoint != NULL)
2019 if (node_allocator_pair.number_of_erased_nodes == 0)
2021 add_group_if_necessary();
2023 PLF_LIST_CONSTRUCT(node_allocator_type, node_allocator_pair, last_endpoint, it.node_pointer, it.node_pointer->previous, std::forward<arguments>(parameters)...);
2025 update_sizes_and_iterators(it);
2026 return iterator(last_endpoint++);
2030 group_pointer_type
const node_group = groups.get_nearest_freelist_group((it.node_pointer != end_iterator.node_pointer) ? it.node_pointer : end_node.previous);
2031 node_pointer_type
const selected_node = node_group->free_list_head;
2032 const node_pointer_type previous = node_group->free_list_head->previous;
2034 PLF_LIST_CONSTRUCT(node_allocator_type, node_allocator_pair, selected_node, it.node_pointer, it.node_pointer->previous, std::forward<arguments>(parameters)...);
2036 node_group->free_list_head = previous;
2037 ++(node_group->number_of_elements);
2038 ++node_pointer_allocator_pair.total_number_of_elements;
2039 --node_allocator_pair.number_of_erased_nodes;
2041 it.node_pointer->previous->next = selected_node;
2042 it.node_pointer->previous = selected_node;
2044 if (it.node_pointer == begin_iterator.node_pointer)
2046 begin_iterator.node_pointer = selected_node;
2048 return iterator(selected_node);
2053 insert_initialize();
2055 #ifdef PLF_LIST_TYPE_TRAITS_SUPPORT
2056 if PLF_LIST_CONSTEXPR (std::is_nothrow_constructible<element_type, arguments ...>::value)
2058 PLF_LIST_CONSTRUCT(node_allocator_type, node_allocator_pair, last_endpoint++, end_iterator.node_pointer, end_iterator.node_pointer, std::forward<arguments>(parameters)...);
2065 PLF_LIST_CONSTRUCT(node_allocator_type, node_allocator_pair, last_endpoint++, end_iterator.node_pointer, end_iterator.node_pointer, std::forward<arguments>(parameters)...);
2074 return begin_iterator;
2080 template<
typename... arguments>
2081 inline PLF_LIST_FORCE_INLINE reference emplace_back(arguments &&... parameters)
2083 return (emplace(end_iterator, std::forward<arguments>(parameters)...)).node_pointer->element;
2088 template<
typename... arguments>
2089 inline PLF_LIST_FORCE_INLINE reference emplace_front(arguments &&... parameters)
2091 return (emplace(begin_iterator, std::forward<arguments>(parameters)...)).node_pointer->element;
2101 void group_fill_position(
const element_type &element, group_size_type number_of_elements, node_pointer_type
const position)
2103 position->previous->next = last_endpoint;
2104 groups.last_endpoint_group->number_of_elements += number_of_elements;
2105 node_pointer_type previous = position->previous;
2109 #ifdef PLF_LIST_TYPE_TRAITS_SUPPORT
2110 if PLF_LIST_CONSTEXPR (std::is_nothrow_copy_constructible<element_type>::value)
2112 #ifdef PLF_LIST_VARIADICS_SUPPORT
2113 PLF_LIST_CONSTRUCT(node_allocator_type, node_allocator_pair, last_endpoint, last_endpoint + 1, previous, element);
2115 PLF_LIST_CONSTRUCT(node_allocator_type, node_allocator_pair, last_endpoint, node(last_endpoint + 1, previous, element));
2123 #ifdef PLF_LIST_VARIADICS_SUPPORT
2124 PLF_LIST_CONSTRUCT(node_allocator_type, node_allocator_pair, last_endpoint, last_endpoint + 1, previous, element);
2126 PLF_LIST_CONSTRUCT(node_allocator_type, node_allocator_pair, last_endpoint, node(last_endpoint + 1, previous, element));
2131 previous->next = position;
2132 position->previous = --previous;
2133 groups.last_endpoint_group->number_of_elements -=
static_cast<group_size_type
>(number_of_elements - (last_endpoint - position));
2138 previous = last_endpoint++;
2139 }
while (--number_of_elements != 0);
2141 previous->next = position;
2142 position->previous = previous;
2151 iterator insert(const_iterator position,
const size_type number_of_elements,
const element_type &element)
2153 if (number_of_elements == 0)
2155 return end_iterator;
2157 else if (number_of_elements == 1)
2159 return insert(position, element);
2163 if (node_pointer_allocator_pair.total_number_of_elements == 0 && last_endpoint != NULL && (
static_cast<size_type
>(groups.block_pointer->beyond_end - groups.block_pointer->nodes) < number_of_elements) && (
static_cast<size_type
>(groups.block_pointer->beyond_end - groups.block_pointer->nodes) < PLF_LIST_BLOCK_MAX))
2169 if (groups.block_pointer == NULL)
2171 if (number_of_elements > PLF_LIST_BLOCK_MAX)
2173 size_type multiples = number_of_elements / PLF_LIST_BLOCK_MAX;
2174 const group_size_type remainder =
static_cast<group_size_type
>(number_of_elements - (multiples++ * PLF_LIST_BLOCK_MAX));
2179 if (remainder >= PLF_LIST_BLOCK_MIN)
2181 groups.initialize(remainder);
2182 end_node.next = end_node.previous = last_endpoint = begin_iterator.node_pointer = groups.last_endpoint_group->nodes;
2183 group_fill_position(element, remainder, end_iterator.node_pointer);
2187 groups.initialize(PLF_LIST_BLOCK_MIN);
2188 end_node.next = end_node.previous = last_endpoint = begin_iterator.node_pointer = groups.last_endpoint_group->nodes;
2189 group_fill_position(element, PLF_LIST_BLOCK_MIN, end_iterator.node_pointer);
2191 groups.add_new(PLF_LIST_BLOCK_MAX - (PLF_LIST_BLOCK_MIN - remainder));
2192 end_node.previous = last_endpoint = groups.last_endpoint_group->nodes;
2193 group_fill_position(element, PLF_LIST_BLOCK_MAX - (PLF_LIST_BLOCK_MIN - remainder), end_iterator.node_pointer);
2199 groups.initialize(PLF_LIST_BLOCK_MAX);
2200 end_node.next = end_node.previous = last_endpoint = begin_iterator.node_pointer = groups.last_endpoint_group->nodes;
2201 group_fill_position(element, PLF_LIST_BLOCK_MAX, end_iterator.node_pointer);
2205 while (--multiples != 0)
2207 groups.add_new(PLF_LIST_BLOCK_MAX);
2208 end_node.previous = last_endpoint = groups.last_endpoint_group->nodes;
2209 group_fill_position(element, PLF_LIST_BLOCK_MAX, end_iterator.node_pointer);
2215 groups.initialize((number_of_elements < PLF_LIST_BLOCK_MIN) ? PLF_LIST_BLOCK_MIN : static_cast<group_size_type>(number_of_elements));
2216 end_node.next = end_node.previous = last_endpoint = begin_iterator.node_pointer = groups.last_endpoint_group->nodes;
2217 group_fill_position(element,
static_cast<group_size_type
>(number_of_elements), end_iterator.node_pointer);
2220 node_pointer_allocator_pair.total_number_of_elements = number_of_elements;
2221 return begin_iterator;
2226 size_type remainder = number_of_elements - 1;
2227 const iterator return_iterator = insert(position, element);
2229 while (node_allocator_pair.number_of_erased_nodes != 0)
2231 insert(position, element);
2232 --node_allocator_pair.number_of_erased_nodes;
2234 if (--remainder == 0)
2236 return return_iterator;
2240 node_pointer_allocator_pair.total_number_of_elements += remainder;
2243 const group_size_type remaining_nodes_in_group =
static_cast<group_size_type
>(groups.last_endpoint_group->beyond_end - last_endpoint);
2245 if (remaining_nodes_in_group != 0)
2247 if (remaining_nodes_in_group < remainder)
2249 group_fill_position(element, remaining_nodes_in_group, position.node_pointer);
2250 remainder -= remaining_nodes_in_group;
2254 group_fill_position(element,
static_cast<group_size_type
>(remainder), position.node_pointer);
2255 return return_iterator;
2261 while ((groups.last_endpoint_group != (groups.block_pointer + groups.size - 1)) & (remainder != 0))
2263 last_endpoint = (++groups.last_endpoint_group)->nodes;
2264 const group_size_type group_size =
static_cast<group_size_type
>(groups.last_endpoint_group->beyond_end - groups.last_endpoint_group->nodes);
2266 if (group_size < remainder)
2268 group_fill_position(element, group_size, position.node_pointer);
2269 remainder -= group_size;
2273 group_fill_position(element,
static_cast<group_size_type
>(remainder), position.node_pointer);
2274 return return_iterator;
2278 size_type multiples = remainder /
static_cast<size_type
>(PLF_LIST_BLOCK_MAX);
2279 remainder -= multiples * PLF_LIST_BLOCK_MAX;
2281 while (multiples-- != 0)
2283 groups.add_new(PLF_LIST_BLOCK_MAX);
2284 last_endpoint = groups.last_endpoint_group->nodes;
2285 group_fill_position(element, PLF_LIST_BLOCK_MAX, position.node_pointer);
2290 groups.add_new(PLF_LIST_BLOCK_MAX);
2291 last_endpoint = groups.last_endpoint_group->nodes;
2292 group_fill_position(element,
static_cast<group_size_type
>(remainder), position.node_pointer);
2295 return return_iterator;
2303 template <
class iterator_type>
2304 #if defined(PLF_LIST_TYPE_TRAITS_SUPPORT)
2305 iterator insert(
const const_iterator position,
typename plf_enable_if_c<(!std::numeric_limits<iterator_type>::is_integer) && (!std::is_same<
typename std::iterator_traits<iterator_type>::iterator_category, std::random_access_iterator_tag>::value), iterator_type>::type first,
const iterator_type last)
2307 iterator insert(
const const_iterator position,
typename plf_enable_if_c<!std::numeric_limits<iterator_type>::is_integer, iterator_type>::type first,
const iterator_type last)
2312 return end_iterator;
2315 const iterator return_iterator = insert(position, *first);
2317 while(++first != last)
2319 insert(position, *first);
2322 return return_iterator;
2327 #if defined(PLF_LIST_TYPE_TRAITS_SUPPORT)
2328 template <
class iterator_type>
2329 iterator insert(
const const_iterator position,
typename plf_enable_if_c<(!std::numeric_limits<iterator_type>::is_integer) && std::is_same<
typename std::iterator_traits<iterator_type>::iterator_category, std::random_access_iterator_tag>::value, iterator_type>::type first,
const iterator_type last)
2331 reserve(node_pointer_allocator_pair.total_number_of_elements +
static_cast<size_type
>(last - first));
2335 return end_iterator;
2338 const iterator return_iterator = insert(position, *first);
2340 while(++first != last)
2342 insert(position, *first);
2345 return return_iterator;
2353 #ifdef PLF_LIST_INITIALIZER_LIST_SUPPORT
2354 inline iterator insert(
const const_iterator it,
const std::initializer_list<element_type> &element_list)
2356 return insert(it, element_list.begin(), element_list.end());
2364 inline PLF_LIST_FORCE_INLINE
void destroy_all_node_pointers(group_pointer_type
const group_to_process,
const node_pointer_type beyond_end_node) PLF_LIST_NOEXCEPT
2366 for (node_pointer_type current_node = group_to_process->nodes; current_node != beyond_end_node; ++current_node)
2368 PLF_LIST_DESTROY(node_pointer_allocator_type, node_pointer_allocator_pair, &(current_node->next));
2369 PLF_LIST_DESTROY(node_pointer_allocator_type, node_pointer_allocator_pair, &(current_node->previous));
2380 iterator erase(
const const_iterator it)
2382 assert(node_pointer_allocator_pair.total_number_of_elements != 0);
2383 assert(it.node_pointer != NULL);
2384 assert(it.node_pointer != end_iterator.node_pointer);
2386 #ifdef PLF_LIST_TYPE_TRAITS_SUPPORT
2387 if PLF_LIST_CONSTEXPR (!(std::is_trivially_destructible<element_type>::value))
2390 PLF_LIST_DESTROY(element_allocator_type, (*
this), &(it.node_pointer->element));
2393 --node_pointer_allocator_pair.total_number_of_elements;
2394 ++node_allocator_pair.number_of_erased_nodes;
2398 group_pointer_type node_group = groups.last_searched_group;
2400 if ((it.node_pointer < node_group->nodes) || (it.node_pointer >= node_group->beyond_end))
2403 const group_pointer_type beyond_end_group = groups.last_endpoint_group + 1;
2404 group_pointer_type left = node_group - 1;
2405 bool right_not_beyond_back = (++node_group < beyond_end_group);
2406 bool left_not_beyond_front = (left >= groups.block_pointer);
2410 if (right_not_beyond_back)
2412 if ((it.node_pointer < node_group->beyond_end) && (it.node_pointer >= node_group->nodes))
2417 right_not_beyond_back = (++node_group < beyond_end_group);
2420 if (left_not_beyond_front)
2422 if ((it.node_pointer >= left->nodes) && (it.node_pointer < left->beyond_end))
2428 left_not_beyond_front = (--left >= groups.block_pointer);
2432 groups.last_searched_group = node_group;
2436 const node_pointer_type previous = it.node_pointer->previous;
2437 const node_pointer_type next = it.node_pointer->next;
2438 next->previous = previous;
2439 previous->next = next;
2441 if (it.node_pointer == begin_iterator.node_pointer)
2443 begin_iterator.node_pointer = next;
2447 const iterator return_iterator(next);
2449 if (--(node_group->number_of_elements) != 0)
2451 it.node_pointer->next = NULL;
2452 it.node_pointer->previous = node_group->free_list_head;
2453 node_group->free_list_head = it.node_pointer;
2454 return return_iterator;
2456 else if (node_group != groups.last_endpoint_group--)
2458 const group_size_type group_size =
static_cast<group_size_type
>(node_group->beyond_end - node_group->nodes);
2459 node_allocator_pair.number_of_erased_nodes -= group_size;
2461 #ifdef PLF_LIST_TYPE_TRAITS_SUPPORT
2462 if PLF_LIST_CONSTEXPR (!std::is_trivially_destructible<node_pointer_type>::value)
2465 destroy_all_node_pointers(node_group, node_group->beyond_end);
2468 node_group->free_list_head = NULL;
2470 if ((group_size == PLF_LIST_BLOCK_MAX) | (node_group >= groups.last_endpoint_group - 1))
2472 groups.move_to_back(node_group);
2476 groups.remove(node_group);
2479 return return_iterator;
2483 #ifdef PLF_LIST_TYPE_TRAITS_SUPPORT
2484 if PLF_LIST_CONSTEXPR (!std::is_trivially_destructible<node_pointer_type>::value)
2487 destroy_all_node_pointers(node_group, last_endpoint);
2490 node_group->free_list_head = NULL;
2492 if (node_pointer_allocator_pair.total_number_of_elements != 0)
2494 node_allocator_pair.number_of_erased_nodes -=
static_cast<group_size_type
>(last_endpoint - node_group->nodes);
2495 last_endpoint = groups.last_endpoint_group->beyond_end;
2499 groups.last_endpoint_group = groups.block_pointer;
2503 return return_iterator;
2511 inline iterator erase(const_iterator iterator1,
const const_iterator iterator2)
2513 while (iterator1 != iterator2)
2515 iterator1 = erase(iterator1);
2523 inline void pop_back()
2525 erase(iterator(end_node.previous));
2530 inline void pop_front()
2532 erase(begin_iterator);
2537 inline list & operator = (
const list &source)
2539 assert (&source !=
this);
2542 reserve(source.node_pointer_allocator_pair.total_number_of_elements);
2543 insert(end_iterator, source.begin_iterator, source.end_iterator);
2550 #ifdef PLF_LIST_MOVE_SEMANTICS_SUPPORT
2552 list & operator = (list &&source) PLF_LIST_NOEXCEPT_MOVE_ASSIGNMENT(allocator_type)
2554 assert (&source !=
this);
2557 groups.destroy_all_data(last_endpoint);
2559 groups = std::move(source.groups);
2560 end_node = std::move(source.end_node);
2561 last_endpoint = std::move(source.last_endpoint);
2562 begin_iterator.node_pointer = (source.begin_iterator.node_pointer == source.end_iterator.node_pointer) ? end_iterator.node_pointer : std::move(source.begin_iterator.node_pointer);
2563 node_pointer_allocator_pair.total_number_of_elements = source.node_pointer_allocator_pair.total_number_of_elements;
2564 node_allocator_pair.number_of_erased_nodes = source.node_allocator_pair.number_of_erased_nodes;
2566 end_node.previous->next = begin_iterator.node_pointer->previous = end_iterator.node_pointer;
2568 source.groups.blank();
2576 #ifdef PLF_LIST_INITIALIZER_LIST_SUPPORT
2577 inline list & operator = (
const std::initializer_list<element_type> &element_list)
2580 insert(begin_iterator, element_list);
2587 bool operator == (
const list &rh)
const PLF_LIST_NOEXCEPT
2589 assert (
this != &rh);
2591 if (node_pointer_allocator_pair.total_number_of_elements != rh.node_pointer_allocator_pair.total_number_of_elements)
2596 for (const_iterator lh_iterator = begin_iterator, rh_iterator = rh.begin_iterator; lh_iterator != end_iterator; ++lh_iterator, ++rh_iterator)
2598 if (*lh_iterator != *rh_iterator)
2609 inline bool operator != (
const list &rh)
const PLF_LIST_NOEXCEPT
2611 return !(*
this == rh);
2616 #ifdef PLF_LIST_CPP20_SUPPORT
2619 inline bool empty() const PLF_LIST_NOEXCEPT
2621 return node_pointer_allocator_pair.total_number_of_elements == 0;
2626 inline size_type size() const PLF_LIST_NOEXCEPT
2628 return node_pointer_allocator_pair.total_number_of_elements;
2633 inline size_type max_size() const PLF_LIST_NOEXCEPT
2635 #ifdef PLF_LIST_ALLOCATOR_TRAITS_SUPPORT
2636 return std::allocator_traits<element_allocator_type>::max_size(*
this);
2638 return element_allocator_type::max_size();
2644 inline size_type capacity() const PLF_LIST_NOEXCEPT
2646 return groups.element_allocator_pair.capacity;
2651 inline size_type memory() const PLF_LIST_NOEXCEPT
2653 return static_cast<size_type
>(
sizeof(*this) + (groups.element_allocator_pair.capacity *
sizeof(node)) + (
sizeof(group) * groups.group_allocator_pair.capacity));
2663 inline bool operator() (
const element_type &a,
const element_type &b)
const PLF_LIST_NOEXCEPT
2672 template <
class comparison_function>
2673 struct sort_dereferencer
2675 comparison_function stored_instance;
2677 explicit sort_dereferencer(
const comparison_function &function_instance):
2678 stored_instance(function_instance)
2681 sort_dereferencer() PLF_LIST_NOEXCEPT
2684 inline bool operator() (
const node_pointer_type first,
const node_pointer_type second)
2686 return stored_instance(first->element, second->element);
2695 template <
class comparison_function>
2696 void sort(comparison_function compare)
2698 if (node_pointer_allocator_pair.total_number_of_elements < 2)
2703 node_pointer_type *
const node_pointers = PLF_LIST_ALLOCATE(node_pointer_allocator_type, node_pointer_allocator_pair, node_pointer_allocator_pair.total_number_of_elements, NULL);
2704 node_pointer_type *node_pointer = node_pointers;
2708 for (group_pointer_type current_group = groups.block_pointer; current_group != groups.last_endpoint_group; ++current_group)
2710 const node_pointer_type end = current_group->beyond_end;
2712 if ((end - current_group->nodes) != current_group->number_of_elements)
2714 for (node_pointer_type current_node = current_group->nodes; current_node != end; ++current_node)
2716 if (current_node->next != NULL)
2718 PLF_LIST_CONSTRUCT(node_pointer_allocator_type, node_pointer_allocator_pair, node_pointer++, current_node);
2724 for (node_pointer_type current_node = current_group->nodes; current_node != end; ++current_node)
2726 PLF_LIST_CONSTRUCT(node_pointer_allocator_type, node_pointer_allocator_pair, node_pointer++, current_node);
2731 if ((last_endpoint - groups.last_endpoint_group->nodes) != groups.last_endpoint_group->number_of_elements)
2733 for (node_pointer_type current_node = groups.last_endpoint_group->nodes; current_node != last_endpoint; ++current_node)
2735 if (current_node->next != NULL)
2737 PLF_LIST_CONSTRUCT(node_pointer_allocator_type, node_pointer_allocator_pair, node_pointer++, current_node);
2743 for (node_pointer_type current_node = groups.last_endpoint_group->nodes; current_node != last_endpoint; ++current_node)
2745 PLF_LIST_CONSTRUCT(node_pointer_allocator_type, node_pointer_allocator_pair, node_pointer++, current_node);
2750 #ifdef GFX_TIMSORT_HPP
2751 gfx::timsort(node_pointers, node_pointers + node_pointer_allocator_pair.total_number_of_elements, sort_dereferencer<comparison_function>(compare));
2753 std::sort(node_pointers, node_pointers + node_pointer_allocator_pair.total_number_of_elements, sort_dereferencer<comparison_function>(compare));
2756 begin_iterator.node_pointer = node_pointers[0];
2757 begin_iterator.node_pointer->next = node_pointers[1];
2758 begin_iterator.node_pointer->previous = end_iterator.node_pointer;
2760 end_node.next = node_pointers[0];
2761 end_node.previous = node_pointers[node_pointer_allocator_pair.total_number_of_elements - 1];
2762 end_node.previous->next = end_iterator.node_pointer;
2763 end_node.previous->previous = node_pointers[node_pointer_allocator_pair.total_number_of_elements - 2];
2765 node_pointer_type *
const back = node_pointers + node_pointer_allocator_pair.total_number_of_elements - 1;
2767 for(node_pointer = node_pointers + 1; node_pointer != back; ++node_pointer)
2769 (*node_pointer)->next = *(node_pointer + 1);
2770 (*node_pointer)->previous = *(node_pointer - 1);
2772 #ifdef PLF_LIST_TYPE_TRAITS_SUPPORT
2773 if PLF_LIST_CONSTEXPR (!std::is_trivially_destructible<node_pointer_type>::value)
2776 PLF_LIST_DESTROY(node_pointer_allocator_type, node_pointer_allocator_pair, node_pointer - 1);
2780 #ifdef PLF_LIST_TYPE_TRAITS_SUPPORT
2781 if PLF_LIST_CONSTEXPR (!std::is_trivially_destructible<node_pointer_type>::value)
2784 PLF_LIST_DESTROY(node_pointer_allocator_type, node_pointer_allocator_pair, back);
2787 PLF_LIST_DEALLOCATE(node_pointer_allocator_type, node_pointer_allocator_pair, node_pointers, node_pointer_allocator_pair.total_number_of_elements);
2799 void reorder(
const iterator position,
const iterator first,
const iterator last) PLF_LIST_NOEXCEPT
2802 const node_pointer_type first_previous = first.node_pointer->previous;
2803 const node_pointer_type last_next = last.node_pointer->next;
2804 const node_pointer_type position_previous = position.node_pointer->previous;
2806 last_next->previous = first_previous;
2807 first.node_pointer->previous->next = last_next;
2809 last.node_pointer->next = position.node_pointer;
2810 first.node_pointer->previous = position_previous;
2812 position_previous->next = first.node_pointer;
2813 position.node_pointer->previous = last.node_pointer;
2815 if (begin_iterator == position)
2817 begin_iterator = first;
2823 inline void reorder(
const iterator position,
const iterator location) PLF_LIST_NOEXCEPT
2825 reorder(position, location, location);
2830 void reserve(size_type reserve_amount)
2832 if (reserve_amount == 0 || reserve_amount <= groups.element_allocator_pair.capacity)
2836 else if (reserve_amount < PLF_LIST_BLOCK_MIN)
2838 reserve_amount = PLF_LIST_BLOCK_MIN;
2840 else if (reserve_amount > max_size())
2842 reserve_amount = max_size();
2846 if (groups.block_pointer != NULL && node_pointer_allocator_pair.total_number_of_elements == 0)
2848 group_size_type end_group_size =
static_cast<group_size_type
>((groups.block_pointer + groups.size - 1)->beyond_end - (groups.block_pointer + groups.size - 1)->nodes);
2850 if (reserve_amount > end_group_size && end_group_size != PLF_LIST_BLOCK_MAX)
2856 size_type number_of_full_groups_needed = reserve_amount / PLF_LIST_BLOCK_MAX;
2857 group_size_type remainder =
static_cast<group_size_type
>(reserve_amount - (number_of_full_groups_needed * PLF_LIST_BLOCK_MAX));
2860 for (group_pointer_type current_group = groups.block_pointer; current_group < groups.block_pointer + groups.size;)
2862 const group_size_type current_group_size =
static_cast<group_size_type
>(groups.block_pointer->beyond_end - groups.block_pointer->nodes);
2864 if (number_of_full_groups_needed != 0 && current_group_size == PLF_LIST_BLOCK_MAX)
2866 --number_of_full_groups_needed;
2869 else if (remainder != 0 && current_group_size >= remainder)
2876 groups.remove(current_group);
2880 last_endpoint = groups.block_pointer->nodes;
2884 reserve_amount -= groups.element_allocator_pair.capacity;
2887 const difference_type last_endpoint_group_number = groups.last_endpoint_group - groups.block_pointer;
2889 size_type number_of_full_groups = (reserve_amount / PLF_LIST_BLOCK_MAX);
2890 reserve_amount -= (number_of_full_groups++ * PLF_LIST_BLOCK_MAX);
2892 if (groups.block_pointer == NULL)
2894 if (reserve_amount != 0)
2896 groups.initialize(
static_cast<group_size_type
>(((reserve_amount < PLF_LIST_BLOCK_MIN) ? PLF_LIST_BLOCK_MIN : reserve_amount)));
2900 groups.initialize(PLF_LIST_BLOCK_MAX);
2901 --number_of_full_groups;
2904 else if (reserve_amount != 0)
2906 const group_size_type last_endpoint_group_capacity =
static_cast<group_size_type
>(groups.last_endpoint_group->beyond_end - groups.last_endpoint_group->nodes);
2907 groups.add_new(
static_cast<group_size_type
>((reserve_amount < last_endpoint_group_capacity) ? last_endpoint_group_capacity : reserve_amount));
2910 while (--number_of_full_groups != 0)
2912 groups.add_new(PLF_LIST_BLOCK_MAX);
2915 groups.last_endpoint_group = groups.block_pointer + last_endpoint_group_number;
2920 inline PLF_LIST_FORCE_INLINE
void free_unused_memory() PLF_LIST_NOEXCEPT
2922 groups.trim_trailing_groups();
2927 void shrink_to_fit()
2929 if ((groups.block_pointer == NULL) | (node_pointer_allocator_pair.total_number_of_elements == groups.element_allocator_pair.capacity))
2933 else if (node_pointer_allocator_pair.total_number_of_elements == 0)
2938 else if (node_allocator_pair.number_of_erased_nodes == 0 && last_endpoint == groups.last_endpoint_group->beyond_end)
2940 groups.trim_trailing_groups();
2944 #ifdef PLF_LIST_MOVE_SEMANTICS_SUPPORT
2946 temp.reserve(node_pointer_allocator_pair.total_number_of_elements);
2948 #ifdef PLF_LIST_TYPE_TRAITS_SUPPORT
2949 if PLF_LIST_CONSTEXPR (std::is_move_assignable<element_type>::value && std::is_move_constructible<element_type>::value)
2951 temp.insert(temp.end_iterator, std::make_move_iterator(begin_iterator), std::make_move_iterator(end_iterator));
2956 temp.insert(temp.end_iterator, begin_iterator, end_iterator);
2959 *
this = std::move(temp);
2971 void append_process(list &source)
2973 if (last_endpoint != groups.last_endpoint_group->beyond_end)
2975 const node_pointer_type back_node = last_endpoint - 1;
2976 for (node_pointer_type current_node = groups.last_endpoint_group->beyond_end - 1; current_node != back_node; --current_node)
2978 current_node->next = NULL;
2979 current_node->previous = groups.last_endpoint_group->free_list_head;
2980 groups.last_endpoint_group->free_list_head = current_node;
2983 node_allocator_pair.number_of_erased_nodes +=
static_cast<size_type
>(groups.last_endpoint_group->beyond_end - last_endpoint);
2986 groups.append(source.groups);
2987 last_endpoint = source.last_endpoint;
2988 node_pointer_allocator_pair.total_number_of_elements += source.node_pointer_allocator_pair.total_number_of_elements;
2997 void splice(iterator position, list &source)
2999 assert(&source !=
this);
3001 if (source.node_pointer_allocator_pair.total_number_of_elements == 0)
3005 else if (node_pointer_allocator_pair.total_number_of_elements == 0)
3007 #ifdef PLF_LIST_MOVE_SEMANTICS_SUPPORT
3008 *
this = std::move(source);
3017 if (position.node_pointer == begin_iterator.node_pointer)
3020 position.node_pointer = end_iterator.node_pointer;
3023 position.node_pointer->previous->next = source.begin_iterator.node_pointer;
3024 source.begin_iterator.node_pointer->previous = position.node_pointer->previous;
3025 position.node_pointer->previous = source.end_node.previous;
3026 source.end_node.previous->next = position.node_pointer;
3028 append_process(source);
3033 template <
class comparison_function>
3034 void merge(list &source, comparison_function compare)
3036 assert(&source !=
this);
3037 splice((source.node_pointer_allocator_pair.total_number_of_elements >= node_pointer_allocator_pair.total_number_of_elements) ? end_iterator : begin_iterator, source);
3043 void merge(list &source)
3045 assert(&source !=
this);
3047 if (source.node_pointer_allocator_pair.total_number_of_elements == 0)
3051 else if (node_pointer_allocator_pair.total_number_of_elements == 0)
3053 #ifdef PLF_LIST_MOVE_SEMANTICS_SUPPORT
3054 *
this = std::move(source);
3063 node_pointer_type current1 = begin_iterator.node_pointer->next, current2 = source.begin_iterator.node_pointer->next;
3064 node_pointer_type previous = source.begin_iterator.node_pointer;
3065 const node_pointer_type source_end = source.end_iterator.node_pointer, this_end = end_iterator.node_pointer;
3067 begin_iterator.node_pointer->next = source.begin_iterator.node_pointer;
3068 source.begin_iterator.node_pointer->previous = begin_iterator.node_pointer;
3071 while ((current1 != this_end) & (current2 != source_end))
3073 previous->next = current1;
3074 current1->previous = previous;
3075 previous = current1;
3076 current1 = current1->next;
3078 previous->next = current2;
3079 current2->previous = previous;
3080 previous = current2;
3081 current2 = current2->next;
3084 if (current1 != this_end)
3086 previous->next = current1;
3087 current1->previous = previous;
3091 end_node.previous = source.end_node.previous;
3092 source.end_node.previous->next = end_iterator.node_pointer;
3095 append_process(source);
3100 void reverse() PLF_LIST_NOEXCEPT
3103 if (node_pointer_allocator_pair.total_number_of_elements > 1)
3105 for (group_pointer_type current_group = groups.block_pointer; current_group != groups.last_endpoint_group; ++current_group)
3107 const node_pointer_type end = current_group->beyond_end;
3109 for (node_pointer_type current_node = current_group->nodes; current_node != end; ++current_node)
3111 if (current_node->next != NULL)
3113 const node_pointer_type temp = current_node->next;
3114 current_node->next = current_node->previous;
3115 current_node->previous = temp;
3120 for (node_pointer_type current_node = groups.last_endpoint_group->nodes; current_node != last_endpoint; ++current_node)
3122 if (current_node->next != NULL)
3124 const node_pointer_type temp = current_node->next;
3125 current_node->next = current_node->previous;
3126 current_node->previous = temp;
3130 const node_pointer_type temp = end_node.previous;
3131 end_node.previous = begin_iterator.node_pointer;
3132 begin_iterator.node_pointer = temp;
3134 end_node.previous->next = end_iterator.node_pointer;
3135 begin_iterator.node_pointer->previous = end_iterator.node_pointer;
3146 inline bool operator() (
const element_type &a,
const element_type &b)
const PLF_LIST_NOEXCEPT
3157 const element_type value;
3159 explicit eq_to(
const element_type store_value):
3163 eq_to() PLF_LIST_NOEXCEPT
3166 inline bool operator() (
const element_type compare_value)
const PLF_LIST_NOEXCEPT
3168 return value == compare_value;
3176 template <
class comparison_function>
3177 size_type unique(comparison_function compare)
3179 const size_type original_number_of_elements = node_pointer_allocator_pair.total_number_of_elements;
3181 if (original_number_of_elements > 1)
3183 element_type *previous = &(begin_iterator.node_pointer->element);
3185 for (iterator current = ++iterator(begin_iterator); current != end_iterator;)
3187 if (compare(*current, *previous))
3189 current = erase(current);
3193 previous = &(current++.node_pointer->element);
3198 return original_number_of_elements - node_pointer_allocator_pair.total_number_of_elements;
3203 inline size_type unique()
3205 return unique(eq());
3210 template <
class predicate_function>
3211 size_type remove_if(predicate_function predicate)
3213 const size_type original_number_of_elements = node_pointer_allocator_pair.total_number_of_elements;
3215 if (original_number_of_elements != 0)
3217 for (group_pointer_type current_group = groups.block_pointer; current_group != groups.last_endpoint_group; ++current_group)
3219 group_size_type num_elements = current_group->number_of_elements;
3220 const node_pointer_type end = current_group->beyond_end;
3222 if (end - current_group->nodes != num_elements)
3224 for (node_pointer_type current_node = current_group->nodes; current_node != end; ++current_node)
3226 if (current_node->next != NULL && predicate(current_node->element))
3228 erase(current_node);
3230 if (--num_elements == 0)
3240 for (node_pointer_type current_node = current_group->nodes; current_node != end; ++current_node)
3242 if (predicate(current_node->element))
3244 erase(current_node);
3246 if (--num_elements == 0)
3256 group_size_type num_elements = groups.last_endpoint_group->number_of_elements;
3258 if (last_endpoint - groups.last_endpoint_group->nodes != num_elements)
3260 for (node_pointer_type current_node = groups.last_endpoint_group->nodes; current_node != last_endpoint; ++current_node)
3262 if (current_node->next != NULL && predicate(current_node->element))
3264 erase(current_node);
3266 if (--num_elements == 0)
3275 for (node_pointer_type current_node = groups.last_endpoint_group->nodes; current_node != last_endpoint; ++current_node)
3277 if (predicate(current_node->element))
3279 erase(current_node);
3281 if (--num_elements == 0)
3290 return original_number_of_elements - node_pointer_allocator_pair.total_number_of_elements;
3295 inline size_type remove(
const element_type &value)
3297 return remove_if(eq_to(value));
3302 void resize(
const size_type number_of_elements,
const element_type &value = element_type())
3304 if (node_pointer_allocator_pair.total_number_of_elements == number_of_elements)
3308 else if (number_of_elements == 0)
3313 else if (node_pointer_allocator_pair.total_number_of_elements < number_of_elements)
3315 insert(end_iterator, number_of_elements - node_pointer_allocator_pair.total_number_of_elements, value);
3319 const_iterator current(end_node.previous);
3321 for (size_type number_to_remove = node_pointer_allocator_pair.total_number_of_elements - number_of_elements; number_to_remove != 0; --number_to_remove)
3323 const node_pointer_type temp = current.node_pointer->previous;
3325 current.node_pointer = temp;
3333 template <
class iterator_type>
3334 inline void assign(
const typename plf_enable_if_c<!std::numeric_limits<iterator_type>::is_integer, iterator_type>::type first,
const iterator_type last)
3337 insert(end_iterator, first, last);
3338 groups.trim_trailing_groups();
3344 inline void assign(
const size_type number_of_elements,
const element_type &value)
3347 reserve(number_of_elements);
3348 insert(end_iterator, number_of_elements, value);
3353 #ifdef PLF_LIST_INITIALIZER_LIST_SUPPORT
3355 inline void assign(
const std::initializer_list<element_type> &element_list)
3358 reserve(element_list.size());
3359 insert(end_iterator, element_list);
3365 inline allocator_type get_allocator() const PLF_LIST_NOEXCEPT
3367 return element_allocator_type();
3372 iterator unordered_find_single(
const element_type &element_to_match)
const PLF_LIST_NOEXCEPT
3374 if (node_pointer_allocator_pair.total_number_of_elements != 0)
3376 for (group_pointer_type current_group = groups.block_pointer; current_group != groups.last_endpoint_group; ++current_group)
3378 const node_pointer_type end = current_group->beyond_end;
3380 if (end - current_group->nodes != current_group->number_of_elements)
3382 for (node_pointer_type current_node = current_group->nodes; current_node != end; ++current_node)
3384 if (current_node->next != NULL && current_node->element == element_to_match)
3386 return iterator(current_node);
3392 for (node_pointer_type current_node = current_group->nodes; current_node != end; ++current_node)
3394 if (current_node->element == element_to_match)
3396 return iterator(current_node);
3402 if (last_endpoint - groups.last_endpoint_group->nodes != groups.last_endpoint_group->number_of_elements)
3404 for (node_pointer_type current_node = groups.last_endpoint_group->nodes; current_node != last_endpoint; ++current_node)
3406 if (current_node->next != NULL && current_node->element == element_to_match)
3408 return iterator(current_node);
3414 for (node_pointer_type current_node = groups.last_endpoint_group->nodes; current_node != last_endpoint; ++current_node)
3416 if (current_node->element == element_to_match)
3418 return iterator(current_node);
3424 return end_iterator;
3429 list<iterator> unordered_find_multiple(
const element_type &element_to_match,
const size_type number_to_find)
const
3431 list<iterator> return_list;
3432 size_type number_found = 0;
3434 if (node_pointer_allocator_pair.total_number_of_elements != 0)
3436 for (group_pointer_type current_group = groups.block_pointer; current_group != groups.last_endpoint_group; ++current_group)
3438 const node_pointer_type end = current_group->beyond_end;
3440 if (end - current_group->nodes != current_group->number_of_elements)
3442 for (node_pointer_type current_node = current_group->nodes; current_node != end; ++current_node)
3444 if (current_node->next != NULL && current_node->element == element_to_match)
3446 return_list.push_back(iterator(current_node));
3448 if (++number_found == number_to_find)
3457 for (node_pointer_type current_node = current_group->nodes; current_node != end; ++current_node)
3459 if (current_node->element == element_to_match)
3461 return_list.push_back(iterator(current_node));
3463 if (++number_found == number_to_find)
3472 if (last_endpoint - groups.last_endpoint_group->nodes != groups.last_endpoint_group->number_of_elements)
3474 for (node_pointer_type current_node = groups.last_endpoint_group->nodes; current_node != last_endpoint; ++current_node)
3476 if (current_node->next != NULL && current_node->element == element_to_match)
3478 return_list.push_back(iterator(current_node));
3480 if (++number_found == number_to_find)
3489 for (node_pointer_type current_node = groups.last_endpoint_group->nodes; current_node != last_endpoint; ++current_node)
3491 if (current_node->element == element_to_match)
3493 return_list.push_back(iterator(current_node));
3495 if (++number_found == number_to_find)
3509 list<iterator> unordered_find_all(
const element_type &element_to_match)
const
3511 list<iterator> return_list;
3513 if (node_pointer_allocator_pair.total_number_of_elements != 0)
3515 for (group_pointer_type current_group = groups.block_pointer; current_group != groups.last_endpoint_group; ++current_group)
3517 const node_pointer_type end = current_group->beyond_end;
3519 if (end - current_group->nodes != current_group->number_of_elements)
3521 for (node_pointer_type current_node = current_group->nodes; current_node != end; ++current_node)
3523 if (current_node->next != NULL && current_node->element == element_to_match)
3525 return_list.push_back(iterator(current_node));
3531 for (node_pointer_type current_node = current_group->nodes; current_node != end; ++current_node)
3533 if (current_node->element == element_to_match)
3535 return_list.push_back(iterator(current_node));
3541 if (last_endpoint - groups.last_endpoint_group->nodes != groups.last_endpoint_group->number_of_elements)
3543 for (node_pointer_type current_node = groups.last_endpoint_group->nodes; current_node != last_endpoint; ++current_node)
3545 if (current_node->next != NULL && current_node->element == element_to_match)
3547 return_list.push_back(iterator(current_node));
3553 for (node_pointer_type current_node = groups.last_endpoint_group->nodes; current_node != last_endpoint; ++current_node)
3555 if (current_node->element == element_to_match)
3557 return_list.push_back(iterator(current_node));
3568 void swap(list &source) PLF_LIST_NOEXCEPT_SWAP(allocator_type)
3570 #ifdef PLF_LIST_MOVE_SEMANTICS_SUPPORT
3571 list temp(std::move(source));
3572 source = std::move(*
this);
3573 *
this = std::move(temp);
3575 groups.swap(source.groups);
3577 const node_pointer_type swap_end_node_previous = end_node.previous, swap_last_endpoint = last_endpoint;
3578 const iterator swap_begin_iterator = begin_iterator;
3579 const size_type swap_total_number_of_elements = node_pointer_allocator_pair.total_number_of_elements, swap_number_of_erased_nodes = node_allocator_pair.number_of_erased_nodes;
3581 last_endpoint = source.last_endpoint;
3582 end_node.next = begin_iterator.node_pointer = (source.begin_iterator.node_pointer != source.end_iterator.node_pointer) ? source.begin_iterator.node_pointer : end_iterator.node_pointer;
3583 end_node.previous = (source.begin_iterator.node_pointer != source.end_iterator.node_pointer) ? source.end_node.previous : end_iterator.node_pointer;
3584 end_node.previous->next = begin_iterator.node_pointer->previous = end_iterator.node_pointer;
3585 node_pointer_allocator_pair.total_number_of_elements = source.node_pointer_allocator_pair.total_number_of_elements;
3586 node_allocator_pair.number_of_erased_nodes = source.node_allocator_pair.number_of_erased_nodes;
3588 source.last_endpoint = swap_last_endpoint;
3589 source.end_node.next = source.begin_iterator.node_pointer = (swap_begin_iterator.node_pointer != end_iterator.node_pointer) ? swap_begin_iterator.node_pointer : source.end_iterator.node_pointer;
3590 source.end_node.previous = (swap_begin_iterator.node_pointer != end_iterator.node_pointer) ? swap_end_node_previous : source.end_iterator.node_pointer;
3591 source.end_node.previous->next = source.begin_iterator.node_pointer->previous = source.end_iterator.node_pointer;
3592 source.node_pointer_allocator_pair.total_number_of_elements = swap_total_number_of_elements;
3593 source.node_allocator_pair.number_of_erased_nodes = swap_number_of_erased_nodes;