Fixes #150 ("Use std::contiguous_iterator_tag if available"), tested in MSVC and GCC.

This commit is contained in:
Ion Gaztañaga
2021-04-21 00:43:31 +02:00
parent c0bfb40f55
commit ad7167c564
4 changed files with 53 additions and 2 deletions

View File

@@ -1341,6 +1341,7 @@ use [*Boost.Container]? There are several reasons for that:
[section:release_notes_boost_1_77_00 Boost 1.77 Release]
* Fixed bugs/issues:
* [@https://github.com/boostorg/container/issues/150 GitHub #150: ['"Use std::contiguous_iterator_tag if available"]].
* [@https://github.com/boostorg/container/issues/184 GitHub #184: ['"Issues with custom exceptions implementation"]].
[endsect]

View File

@@ -53,6 +53,9 @@ struct allocator_arg_t;
struct piecewise_construct_t;
template <class Ptr>
struct pointer_traits;
BOOST_MOVE_STD_NS_END
#include <boost/move/detail/std_ns_end.hpp>

View File

@@ -82,7 +82,17 @@ class vec_iterator
{
public:
typedef std::random_access_iterator_tag iterator_category;
typedef std::contiguous_iterator_tag iterator_concept;
typedef typename boost::intrusive::pointer_traits<Pointer>::element_type value_type;
//Defining element_type to make libstdc++'s std::pointer_traits well-formed leads to ambiguity
//due to LWG3446. So we need to specialize std::pointer_traits. See
//https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96416 for details. /Many thanks to Jonathan Wakely
//for explaning the issue.
#ifndef BOOST_GNU_STDLIB
//Define element_
typedef typename boost::intrusive::pointer_traits<Pointer>::element_type element_type;
#endif
typedef typename boost::intrusive::pointer_traits<Pointer>::difference_type difference_type;
typedef typename dtl::if_c
< IsConst
@@ -3378,6 +3388,20 @@ struct has_trivial_destructor_after_move<boost::container::vector<T, Allocator,
}
//See comments on vec_iterator::element_type to know why is this needed
#ifdef BOOST_GNU_STDLIB
BOOST_MOVE_STD_NS_BEG
template <class Pointer, bool IsConst>
struct pointer_traits< boost::container::vec_iterator<Pointer, IsConst> >
: public boost::intrusive::pointer_traits< boost::container::vec_iterator<Pointer, IsConst> >
{};
BOOST_MOVE_STD_NS_END
#endif //BOOST_GNU_STDLIB
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
#include <boost/container/detail/config_end.hpp>

View File

@@ -194,7 +194,25 @@ bool test_merge_empty_free()
vector< int, check_dealloc_allocator<int> > empty;
empty.merge(source.begin(), source.end());
return empty.get_stored_allocator().deallocate_called_without_allocate_;
return !empty.get_stored_allocator().deallocate_called_without_allocate_;
}
#ifdef __cpp_lib_span
#include <span>
#endif
bool test_span_conversion()
{
#ifdef __cpp_lib_span
{
boost::container::vector myVec{1, 2, 3, 4, 5};
std::span mySpan1{myVec}; // (1)
std::span mySpan2{myVec.data(), myVec.size()}; // (2)
return mySpan1.size() == myVec.size() && mySpan1.size() == mySpan2.size();
}
#else
return true;
#endif
}
int main()
@@ -331,11 +349,16 @@ int main()
}
#endif
if (test_merge_empty_free()) {
if (!test_merge_empty_free()) {
std::cerr << "Merge into empty vector test failed" << std::endl;
return 1;
}
if (!test_span_conversion()) {
std::cerr << "Span conversion failed" << std::endl;
return 1;
}
////////////////////////////////////
// has_trivial_destructor_after_move testing
////////////////////////////////////