From 11d64d12a0135e745f0e5f867076aa41c5e8ba5b Mon Sep 17 00:00:00 2001 From: rexy712 Date: Tue, 19 Jul 2022 17:39:29 -0700 Subject: [PATCH] I couldn't figure out how to make construct_at work with an aggregate. I checked the libstdc++ sources and they call placement new directly, so I'm giving up on that. Changed node over to manual constructors and it seems to work much better. Also made it so list constructors don't call 'assign' because that required stored types to implement assignment operators during construction. --- include/rexy/list.hpp | 11 ++++--- include/rexy/list.tpp | 70 ++++++++++++++++++++++++++++++------------- 2 files changed, 56 insertions(+), 25 deletions(-) diff --git a/include/rexy/list.hpp b/include/rexy/list.hpp index 62fb2a0..c96d2dc 100644 --- a/include/rexy/list.hpp +++ b/include/rexy/list.hpp @@ -193,15 +193,18 @@ namespace rexy{ template REXY_CPP20_CONSTEXPR void sort(Comp comp); private: + template + REXY_CPP20_CONSTEXPR void iterator_initialize_(InputIt first, InputIt last); + REXY_CPP20_CONSTEXPR void constant_initialize_(size_type count, const_reference value); + REXY_CPP20_CONSTEXPR void default_initialize_(size_type count); + template - iterator mergesort(iterator first, size_type firstlen, Comp comp); - std::pair ms_split(iterator it, size_type len); + static iterator mergesort(iterator first, size_type firstlen, Comp comp); + static std::pair ms_split(iterator it, size_type len); static void insert_node_(detail::node_base* prev, detail::node_base* n); static void remove_node_(detail::node_base* rm); static detail::node_base* get_next_then_move_node_(detail::node_base* dest, detail::node_base* n); - constexpr auto& sentinel(void){return this->m_sentinel;} - constexpr const auto& sentinel(void)const{return this->m_sentinel;} }; } diff --git a/include/rexy/list.tpp b/include/rexy/list.tpp index f4ec3fd..2141d64 100644 --- a/include/rexy/list.tpp +++ b/include/rexy/list.tpp @@ -33,8 +33,25 @@ namespace rexy{ struct node : public node_base{ T data; - node* next(void)const{return static_cast(node_base::next);} - node* prev(void)const{return static_cast(node_base::prev);} + constexpr node(node_base* next, node_base* prev, const T& d): + node_base{next, prev}, + data(d){} + constexpr node(node_base* next, node_base* prev, T&& d): + node_base{next, prev}, + data(std::move(d)){} + template + constexpr node(node_base* next, node_base* prev, Args&&... args): + node_base{next, prev}, + data(std::forward(args)...){} + constexpr node(const node& n): + node_base(n), + data(n.data){} + constexpr node(node&& n): + node_base(std::move(n)), + data(std::move(n.data)){} + + constexpr node* next(void)const{return static_cast(node_base::next);} + constexpr node* prev(void)const{return static_cast(node_base::prev);} }; template @@ -162,26 +179,26 @@ namespace rexy{ REXY_CPP20_CONSTEXPR list::list(size_type count, const_reference value, const allocator_type& alloc): node_allocator_type(alloc) { - assign(count, value); + constant_initialize_(count, value); } template REXY_CPP20_CONSTEXPR list::list(size_type count, const allocator_type& alloc): node_allocator_type(alloc) { - assign(count, value_type()); + default_initialize_(count); } template template REXY_CPP20_CONSTEXPR list::list(InputIt first, InputIt last, const allocator_type& alloc): node_allocator_type(alloc) { - assign(first, last); + iterator_initialize_(first, last); } template REXY_CPP20_CONSTEXPR list::list(const list& other, const allocator_type& alloc): node_allocator_type(alloc) { - assign(other.begin(), other.end()); + iterator_initialize_(other.begin(), other.end()); } template REXY_CPP20_CONSTEXPR list::list(list&& other, const allocator_type& alloc): @@ -193,7 +210,7 @@ namespace rexy{ REXY_CPP20_CONSTEXPR list::list(std::initializer_list l, const allocator_type& alloc): node_allocator_type(alloc) { - assign(l); + iterator_initialize_(l.begin(), l.end()); } template @@ -253,6 +270,26 @@ namespace rexy{ REXY_CPP20_CONSTEXPR void list::assign(size_type count, const_reference value){ assign(sized_constant_iterator{value, count}, sized_constant_iterator{{}, 0}); } + + template + template + REXY_CPP20_CONSTEXPR void list::iterator_initialize_(InputIt first, InputIt last){ + for(;first != last;++first){ + emplace_back(*first); + } + } + template + REXY_CPP20_CONSTEXPR void list::constant_initialize_(size_type count, const_reference value){ + for(;count > 0;--count){ + emplace_back(value); + } + } + template + REXY_CPP20_CONSTEXPR void list::default_initialize_(size_type count){ + for(;count > 0;--count){ + emplace_back(); + } + } template template REXY_CPP20_CONSTEXPR void list::assign(InputIt first, InputIt last){ @@ -347,12 +384,7 @@ namespace rexy{ auto* next = prev->next; prev->next = this->allocate(1); next->prev = prev->next; -#ifdef __clang__ - //clang won't let construct at emplace without creating a temporary here... - std::construct_at(static_cast(prev->next), node{{next, prev}, std::move(value)}); -#else - std::construct_at(static_cast(prev->next), detail::node_base{next, prev}, std::move(value)); -#endif + std::construct_at(static_cast(prev->next), next, prev, std::move(value)); ++m_size; return iterator{prev->next}; } @@ -385,11 +417,7 @@ namespace rexy{ auto* next = prev->next; prev->next = this->allocate(1); next->prev = prev->next; -#ifdef __clang__ - std::construct_at(static_cast(prev->next), node{{next, prev}, value_type{std::forward(args)...}}); -#else - std::construct_at(static_cast(prev->next), detail::node_base{next, prev}, value_type{std::forward(args)...}); -#endif + std::construct_at(static_cast(prev->next), next, prev, std::forward(args)...); ++m_size; return iterator{prev->next}; } @@ -415,16 +443,16 @@ namespace rexy{ template REXY_CPP20_CONSTEXPR auto list::push_back(const_reference value) -> reference{ - return insert(cend(), value); + return *insert(cend(), value); } template REXY_CPP20_CONSTEXPR auto list::push_back(value_type&& value) -> reference{ - return insert(cend(), std::move(value)); + return *insert(cend(), std::move(value)); } template template REXY_CPP20_CONSTEXPR auto list::emplace_back(Args&&... args) -> reference{ - return emplace(cend(), std::forward(args)...); + return *emplace(cend(), std::forward(args)...); } template