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.

This commit is contained in:
rexy712 2022-07-19 17:39:29 -07:00
parent b6a8c83e0b
commit 11d64d12a0
2 changed files with 56 additions and 25 deletions

View File

@ -193,15 +193,18 @@ namespace rexy{
template<class Comp>
REXY_CPP20_CONSTEXPR void sort(Comp comp);
private:
template<class InputIt>
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<class Comp>
iterator mergesort(iterator first, size_type firstlen, Comp comp);
std::pair<iterator,size_type> ms_split(iterator it, size_type len);
static iterator mergesort(iterator first, size_type firstlen, Comp comp);
static std::pair<iterator,size_type> 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;}
};
}

View File

@ -33,8 +33,25 @@ namespace rexy{
struct node : public node_base{
T data;
node* next(void)const{return static_cast<node*>(node_base::next);}
node* prev(void)const{return static_cast<node*>(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<class... Args>
constexpr node(node_base* next, node_base* prev, Args&&... args):
node_base{next, prev},
data(std::forward<Args>(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*>(node_base::next);}
constexpr node* prev(void)const{return static_cast<node*>(node_base::prev);}
};
template<class T>
@ -162,26 +179,26 @@ namespace rexy{
REXY_CPP20_CONSTEXPR list<T,Alloc>::list(size_type count, const_reference value, const allocator_type& alloc):
node_allocator_type(alloc)
{
assign(count, value);
constant_initialize_(count, value);
}
template<class T, class Alloc>
REXY_CPP20_CONSTEXPR list<T,Alloc>::list(size_type count, const allocator_type& alloc):
node_allocator_type(alloc)
{
assign(count, value_type());
default_initialize_(count);
}
template<class T, class Alloc>
template<class InputIt>
REXY_CPP20_CONSTEXPR list<T,Alloc>::list(InputIt first, InputIt last, const allocator_type& alloc):
node_allocator_type(alloc)
{
assign(first, last);
iterator_initialize_(first, last);
}
template<class T, class Alloc>
REXY_CPP20_CONSTEXPR list<T,Alloc>::list(const list& other, const allocator_type& alloc):
node_allocator_type(alloc)
{
assign(other.begin(), other.end());
iterator_initialize_(other.begin(), other.end());
}
template<class T, class Alloc>
REXY_CPP20_CONSTEXPR list<T,Alloc>::list(list&& other, const allocator_type& alloc):
@ -193,7 +210,7 @@ namespace rexy{
REXY_CPP20_CONSTEXPR list<T,Alloc>::list(std::initializer_list<value_type> l, const allocator_type& alloc):
node_allocator_type(alloc)
{
assign(l);
iterator_initialize_(l.begin(), l.end());
}
template<class T, class Alloc>
@ -253,6 +270,26 @@ namespace rexy{
REXY_CPP20_CONSTEXPR void list<T,Alloc>::assign(size_type count, const_reference value){
assign(sized_constant_iterator{value, count}, sized_constant_iterator<value_type>{{}, 0});
}
template<class T, class Alloc>
template<class InputIt>
REXY_CPP20_CONSTEXPR void list<T,Alloc>::iterator_initialize_(InputIt first, InputIt last){
for(;first != last;++first){
emplace_back(*first);
}
}
template<class T, class Alloc>
REXY_CPP20_CONSTEXPR void list<T,Alloc>::constant_initialize_(size_type count, const_reference value){
for(;count > 0;--count){
emplace_back(value);
}
}
template<class T, class Alloc>
REXY_CPP20_CONSTEXPR void list<T,Alloc>::default_initialize_(size_type count){
for(;count > 0;--count){
emplace_back();
}
}
template<class T, class Alloc>
template<class InputIt>
REXY_CPP20_CONSTEXPR void list<T,Alloc>::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<node*>(prev->next), node{{next, prev}, std::move(value)});
#else
std::construct_at(static_cast<node*>(prev->next), detail::node_base{next, prev}, std::move(value));
#endif
std::construct_at(static_cast<node*>(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<node*>(prev->next), node{{next, prev}, value_type{std::forward<Args>(args)...}});
#else
std::construct_at(static_cast<node*>(prev->next), detail::node_base{next, prev}, value_type{std::forward<Args>(args)...});
#endif
std::construct_at(static_cast<node*>(prev->next), next, prev, std::forward<Args>(args)...);
++m_size;
return iterator{prev->next};
}
@ -415,16 +443,16 @@ namespace rexy{
template<class T, class Alloc>
REXY_CPP20_CONSTEXPR auto list<T,Alloc>::push_back(const_reference value) -> reference{
return insert(cend(), value);
return *insert(cend(), value);
}
template<class T, class Alloc>
REXY_CPP20_CONSTEXPR auto list<T,Alloc>::push_back(value_type&& value) -> reference{
return insert(cend(), std::move(value));
return *insert(cend(), std::move(value));
}
template<class T, class Alloc>
template<class... Args>
REXY_CPP20_CONSTEXPR auto list<T,Alloc>::emplace_back(Args&&... args) -> reference{
return emplace(cend(), std::forward<Args>(args)...);
return *emplace(cend(), std::forward<Args>(args)...);
}
template<class T, class Alloc>