refactored proxy_erase to reduce template instantiations and strengthen misuse avoidance

This commit is contained in:
joaquintides
2023-06-17 11:17:15 +02:00
committed by Christian Mazakas
parent 2b6cfe4f3c
commit 2eebe157fd
5 changed files with 53 additions and 31 deletions

View File

@ -123,6 +123,7 @@ public:
private:
template<typename,typename,bool> friend class table_iterator;
template<typename> friend class table_erase_return_type;
template<typename,typename,typename,typename> friend class table;
table_iterator(Group* pg,std::size_t n,const table_element_type* p_):
@ -198,6 +199,45 @@ private:
table_element_type *p=nullptr;
};
/* Returned by table::erase([const_]iterator) to avoid iterator increment
* if discarded.
*/
template<typename Iterator>
class table_erase_return_type;
template<typename TypePolicy,typename Group,bool Const>
class table_erase_return_type<table_iterator<TypePolicy,Group,Const>>
{
using iterator=table_iterator<TypePolicy,Group,Const>;
using const_iterator=table_iterator<TypePolicy,Group,true>;
public:
/* can't delete it because VS in pre-C++17 mode needs to see it for RVO */
table_erase_return_type(const table_erase_return_type&);
operator iterator()const noexcept
{
auto it=pos;
it.increment(); /* valid even if *it was erased */
return iterator(const_iterator_cast_tag{},it);
}
template<
bool dependent_value=false,
typename std::enable_if<!Const||dependent_value>::type* =nullptr
>
operator const_iterator()const noexcept{return this->operator iterator();}
private:
template<typename,typename,typename,typename> friend class table;
table_erase_return_type(const_iterator pos_):pos{pos_}{}
table_erase_return_type& operator=(const table_erase_return_type&)=delete;
const_iterator pos;
};
/* foa::table interface departs in a number of ways from that of C++ unordered
* associative containers because it's not for end-user consumption
* (boost::unordered_(flat|node)_(map|set) wrappers complete it as
@ -271,6 +311,7 @@ public:
has_mutable_iterator,
table_iterator<type_policy,group_type,false>,
const_iterator>::type;
using erase_return_type=table_erase_return_type<iterator>;
table(
std::size_t n=default_bucket_count,const Hash& h_=Hash(),
@ -348,40 +389,19 @@ public:
>::type
insert(element_type&& x){return emplace_impl(std::move(x));}
struct proxy_erase {
const_iterator pos;
operator iterator()const noexcept
{
auto it=pos;
it.increment();
return iterator(const_iterator_cast_tag{},it);
}
template<
bool dependent_value=false,
typename std::enable_if<
has_mutable_iterator||dependent_value>::type* =nullptr
>
operator const_iterator()const noexcept
{
auto it=pos;
it.increment();
return it;
}
};
template<
bool dependent_value=false,
typename std::enable_if<
has_mutable_iterator||dependent_value>::type* =nullptr
>
proxy_erase erase(iterator pos)noexcept{return erase(const_iterator(pos));}
erase_return_type erase(iterator pos)noexcept
{return erase(const_iterator(pos));}
BOOST_FORCEINLINE
proxy_erase erase(const_iterator pos)noexcept
erase_return_type erase(const_iterator pos)noexcept
{
super::erase(pos.pc,pos.p);
return proxy_erase{pos};
return {pos};
}
template<typename Key>

View File

@ -381,12 +381,13 @@ namespace boost {
.first;
}
BOOST_FORCEINLINE typename table_type::proxy_erase erase(iterator pos)
BOOST_FORCEINLINE typename table_type::erase_return_type erase(
iterator pos)
{
return table_.erase(pos);
}
BOOST_FORCEINLINE typename table_type::proxy_erase erase(
BOOST_FORCEINLINE typename table_type::erase_return_type erase(
const_iterator pos)
{
return table_.erase(pos);

View File

@ -282,7 +282,7 @@ namespace boost {
return table_.emplace(std::forward<Args>(args)...).first;
}
BOOST_FORCEINLINE typename table_type::proxy_erase erase(
BOOST_FORCEINLINE typename table_type::erase_return_type erase(
const_iterator pos)
{
return table_.erase(pos);

View File

@ -458,12 +458,13 @@ namespace boost {
.first;
}
BOOST_FORCEINLINE typename table_type::proxy_erase erase(iterator pos)
BOOST_FORCEINLINE typename table_type::erase_return_type erase(
iterator pos)
{
return table_.erase(pos);
}
BOOST_FORCEINLINE typename table_type::proxy_erase erase(
BOOST_FORCEINLINE typename table_type::erase_return_type erase(
const_iterator pos)
{
return table_.erase(pos);

View File

@ -352,7 +352,7 @@ namespace boost {
return table_.emplace(std::forward<Args>(args)...).first;
}
BOOST_FORCEINLINE typename table_type::proxy_erase erase(
BOOST_FORCEINLINE typename table_type::erase_return_type erase(
const_iterator pos)
{
return table_.erase(pos);