mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-11-30 07:14:09 +08:00
libstdc++: Add P1206R7 from_range members to std::list and std::forward_list [PR111055]
This is another piece of P1206R7, adding new members to std::list and std::forward_list. libstdc++-v3/ChangeLog: PR libstdc++/111055 * include/bits/forward_list.h (forward_list(from_range, R&&, const Alloc&), assign_range) (prepend_range, insert_range_after): Define. * include/bits/stl_list.h (list(from_range, R&&, const Alloc&)) (assign_range, prepend_range, append_range, insert_range): Define. * include/debug/forward_list (forward_list(from_range, R&&, const Alloc&), assign_range) (prepend_range, insert_range_after): Define. * include/debug/list (list(from_range, R&&, const Alloc&)) (assign_range, prepend_range, append_range, insert_range): Define. * testsuite/23_containers/forward_list/cons/from_range.cc: New test. * testsuite/23_containers/forward_list/modifiers/assign_range.cc: New test. * testsuite/23_containers/forward_list/modifiers/insert_range_after.cc: New test. * testsuite/23_containers/forward_list/modifiers/prepend_range.cc: New test. * testsuite/23_containers/list/cons/from_range.cc: New test. * testsuite/23_containers/list/modifiers/append_range.cc: New test. * testsuite/23_containers/list/modifiers/assign/assign_range.cc: New test. * testsuite/23_containers/list/modifiers/insert/insert_range.cc: New test. * testsuite/23_containers/list/modifiers/prepend_range.cc: New test. Reviewed-by: Patrick Palka <ppalka@redhat.com>
This commit is contained in:
parent
253fe0f626
commit
7a4fced2b1
@ -42,6 +42,10 @@
|
||||
#include <bits/allocator.h>
|
||||
#include <ext/alloc_traits.h>
|
||||
#include <ext/aligned_buffer.h>
|
||||
#if __glibcxx_ranges_to_container // C++ >= 23
|
||||
# include <bits/ranges_base.h> // ranges::begin, ranges::distance etc.
|
||||
# include <bits/ranges_util.h> // ranges::subrange
|
||||
#endif
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
@ -564,6 +568,30 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||
: _Base(_Node_alloc_type(__al))
|
||||
{ _M_range_initialize(__first, __last); }
|
||||
|
||||
#if __glibcxx_ranges_to_container // C++ >= 23
|
||||
/**
|
||||
* @brief Construct a forward_list from a range.
|
||||
* @param __rg An input range with elements that are convertible to
|
||||
* the forward_list's value_type.
|
||||
* @param __a An allocator.
|
||||
*
|
||||
* @since C++23
|
||||
*/
|
||||
template<__detail::__container_compatible_range<_Tp> _Rg>
|
||||
forward_list(from_range_t, _Rg&& __rg, const _Alloc& __a = _Alloc())
|
||||
: _Base(_Node_alloc_type(__a))
|
||||
{
|
||||
_Node_base* __to = &this->_M_impl._M_head;
|
||||
auto __first = ranges::begin(__rg);
|
||||
const auto __last = ranges::end(__rg);
|
||||
for (; __first != __last; ++__first)
|
||||
{
|
||||
__to->_M_next = this->_M_create_node(*__first);
|
||||
__to = __to->_M_next;
|
||||
}
|
||||
}
|
||||
#endif // ranges_to_container
|
||||
|
||||
/**
|
||||
* @brief The %forward_list copy constructor.
|
||||
* @param __list A %forward_list of identical element and allocator
|
||||
@ -675,6 +703,39 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||
_M_assign(__first, __last, __assignable());
|
||||
}
|
||||
|
||||
#if __glibcxx_ranges_to_container // C++ >= 23
|
||||
/**
|
||||
* @brief Assign a range to a forward_list.
|
||||
* @since C++23
|
||||
*/
|
||||
template<__detail::__container_compatible_range<_Tp> _Rg>
|
||||
void
|
||||
assign_range(_Rg&& __rg)
|
||||
{
|
||||
static_assert(assignable_from<_Tp&, ranges::range_reference_t<_Rg>>);
|
||||
|
||||
auto __first = ranges::begin(__rg);
|
||||
const auto __last = ranges::end(__rg);
|
||||
iterator __prev = before_begin();
|
||||
iterator __curr = begin();
|
||||
const iterator __end = end();
|
||||
|
||||
while (__curr != __end && __first != __last)
|
||||
{
|
||||
*__curr = *__first;
|
||||
__prev = __curr;
|
||||
++__first;
|
||||
++__curr;
|
||||
}
|
||||
|
||||
if (__curr != __end)
|
||||
erase_after(__prev, __end);
|
||||
else
|
||||
insert_range_after(__prev,
|
||||
ranges::subrange(std::move(__first), __last));
|
||||
}
|
||||
#endif // ranges_to_container
|
||||
|
||||
/**
|
||||
* @brief Assigns a given value to a %forward_list.
|
||||
* @param __n Number of elements to be assigned.
|
||||
@ -888,6 +949,33 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||
push_front(_Tp&& __val)
|
||||
{ this->_M_insert_after(cbefore_begin(), std::move(__val)); }
|
||||
|
||||
#if __glibcxx_ranges_to_container // C++ >= 23
|
||||
/**
|
||||
* @brief Insert a range at the beginning of a forward_list.
|
||||
* @param __rg An input range with elements that are convertible to
|
||||
* the forward_list's value_type.
|
||||
*
|
||||
* The inserted elements will be in the same order as in the range,
|
||||
* so they are not reversed as would happen with a simple loop calling
|
||||
* emplace_front for each element of the range.
|
||||
*
|
||||
* No iterators to existing elements are invalidated by this function.
|
||||
* If the insertion fails due to an exception, no elements will be added
|
||||
* and so the list will be unchanged.
|
||||
*
|
||||
* @since C++23
|
||||
*/
|
||||
template<__detail::__container_compatible_range<_Tp> _Rg>
|
||||
void
|
||||
prepend_range(_Rg&& __rg)
|
||||
{
|
||||
forward_list __tmp(from_range, std::forward<_Rg>(__rg),
|
||||
get_allocator());
|
||||
if (!__tmp.empty())
|
||||
splice_after(before_begin(), __tmp);
|
||||
}
|
||||
#endif // ranges_to_container
|
||||
|
||||
/**
|
||||
* @brief Removes first element.
|
||||
*
|
||||
@ -1004,6 +1092,32 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||
insert_after(const_iterator __pos, std::initializer_list<_Tp> __il)
|
||||
{ return insert_after(__pos, __il.begin(), __il.end()); }
|
||||
|
||||
#if __glibcxx_ranges_to_container // C++ >= 23
|
||||
/**
|
||||
* @brief Insert a rangeinto a forward_list.
|
||||
* @param __position An iterator.
|
||||
* @param __rg An input range of elements that can be converted to
|
||||
* the forward_list's value type.
|
||||
* @return An iterator pointing to the last element inserted,
|
||||
* or `__position` if the range is empty.
|
||||
*
|
||||
* Inserts the elements of `__rg` after `__position`.
|
||||
* No iterators to existing elements are invalidated by this function.
|
||||
* If the insertion fails due to an exception, no elements will be added
|
||||
* and so the list will be unchanged.
|
||||
*
|
||||
* @since C++23
|
||||
*/
|
||||
template<__detail::__container_compatible_range<_Tp> _Rg>
|
||||
iterator
|
||||
insert_range_after(const_iterator __position, _Rg&& __rg)
|
||||
{
|
||||
forward_list __tmp(from_range, std::forward<_Rg>(__rg),
|
||||
get_allocator());
|
||||
return _M_splice_after(__position, __tmp.before_begin(), __tmp.end());
|
||||
}
|
||||
#endif // ranges_to_container
|
||||
|
||||
/**
|
||||
* @brief Removes the element pointed to by the iterator following
|
||||
* @c pos.
|
||||
@ -1438,6 +1552,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||
typename = _RequireAllocator<_Allocator>>
|
||||
forward_list(_InputIterator, _InputIterator, _Allocator = _Allocator())
|
||||
-> forward_list<_ValT, _Allocator>;
|
||||
|
||||
#if __glibcxx_ranges_to_container // C++ >= 23
|
||||
template<ranges::input_range _Rg,
|
||||
typename _Allocator = allocator<ranges::range_value_t<_Rg>>>
|
||||
forward_list(from_range_t, _Rg&&, _Allocator = _Allocator())
|
||||
-> forward_list<ranges::range_value_t<_Rg>, _Allocator>;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
@ -64,6 +64,10 @@
|
||||
#include <bits/allocated_ptr.h>
|
||||
#include <ext/aligned_buffer.h>
|
||||
#endif
|
||||
#if __glibcxx_ranges_to_container // C++ >= 23
|
||||
# include <bits/ranges_base.h> // ranges::begin, ranges::distance etc.
|
||||
# include <bits/ranges_util.h> // ranges::subrange
|
||||
#endif
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
@ -892,6 +896,22 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
||||
}
|
||||
#endif
|
||||
|
||||
#if __glibcxx_ranges_to_container // C++ >= 23
|
||||
/**
|
||||
* @brief Construct a list from a range.
|
||||
* @since C++23
|
||||
*/
|
||||
template<__detail::__container_compatible_range<_Tp> _Rg>
|
||||
list(from_range_t, _Rg&& __rg, const _Alloc& __a = _Alloc())
|
||||
: _Base(_Node_alloc_type(__a))
|
||||
{
|
||||
auto __first = ranges::begin(__rg);
|
||||
const auto __last = ranges::end(__rg);
|
||||
for (; __first != __last; ++__first)
|
||||
emplace_back(*__first);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
/**
|
||||
* No explicit dtor needed as the _Base dtor takes care of
|
||||
@ -951,6 +971,32 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
||||
}
|
||||
#endif
|
||||
|
||||
#if __glibcxx_ranges_to_container // C++ >= 23
|
||||
/**
|
||||
* @brief Assign a range to a list.
|
||||
* @since C++23
|
||||
*/
|
||||
template<__detail::__container_compatible_range<_Tp> _Rg>
|
||||
void
|
||||
assign_range(_Rg&& __rg)
|
||||
{
|
||||
static_assert(assignable_from<_Tp&, ranges::range_reference_t<_Rg>>);
|
||||
|
||||
iterator __first1 = begin();
|
||||
const iterator __last1 = end();
|
||||
auto __first2 = ranges::begin(__rg);
|
||||
const auto __last2 = ranges::end(__rg);
|
||||
for (; __first1 != __last1 && __first2 != __last2;
|
||||
++__first1, (void)++__first2)
|
||||
*__first1 = *__first2;
|
||||
if (__first2 == __last2)
|
||||
erase(__first1, __last1);
|
||||
else
|
||||
insert_range(__last1,
|
||||
ranges::subrange(std::move(__first2), __last2));
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Assigns a given value to a %list.
|
||||
* @param __n Number of elements to be assigned.
|
||||
@ -1275,6 +1321,50 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
||||
}
|
||||
#endif
|
||||
|
||||
#if __glibcxx_ranges_to_container // C++ >= 23
|
||||
/**
|
||||
* @brief Insert a range at the beginning of a list.
|
||||
* @param __rg An input range of elements that can be converted to
|
||||
* the list's value type.
|
||||
*
|
||||
* Inserts the elements of `__rg` at the beginning of the list.
|
||||
* No iterators to existing elements are invalidated by this function.
|
||||
* If the insertion fails due to an exception, no elements will be added
|
||||
* and so the list will be unchanged.
|
||||
*
|
||||
* @since C++23
|
||||
*/
|
||||
template<__detail::__container_compatible_range<_Tp> _Rg>
|
||||
void
|
||||
prepend_range(_Rg&& __rg)
|
||||
{
|
||||
list __tmp(from_range, std::forward<_Rg>(__rg), get_allocator());
|
||||
if (!__tmp.empty())
|
||||
splice(begin(), __tmp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Insert a range at the end of a list.
|
||||
* @param __rg An input range of elements that can be converted to
|
||||
* the list's value type.
|
||||
*
|
||||
* Inserts the elements of `__rg` at the end of the list.
|
||||
* No iterators to existing elements are invalidated by this function.
|
||||
* If the insertion fails due to an exception, no elements will be added
|
||||
* and so the list will be unchanged.
|
||||
*
|
||||
* @since C++23
|
||||
*/
|
||||
template<__detail::__container_compatible_range<_Tp> _Rg>
|
||||
void
|
||||
append_range(_Rg&& __rg)
|
||||
{
|
||||
list __tmp(from_range, std::forward<_Rg>(__rg), get_allocator());
|
||||
if (!__tmp.empty())
|
||||
splice(end(), __tmp);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Removes first element.
|
||||
*
|
||||
@ -1505,6 +1595,37 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
||||
}
|
||||
#endif
|
||||
|
||||
#if __glibcxx_ranges_to_container // C++ >= 23
|
||||
/**
|
||||
* @brief Insert a range into a list.
|
||||
* @param __position An iterator.
|
||||
* @param __rg An input range of elements that can be converted to
|
||||
* the list's value type.
|
||||
* @return An iterator pointing to the first element inserted,
|
||||
* or `__position` if the range is empty.
|
||||
*
|
||||
* Inserts the elements of `__rg` before `__position`.
|
||||
* No iterators to existing elements are invalidated by this function.
|
||||
* If the insertion fails due to an exception, no elements will be added
|
||||
* and so the list will be unchanged.
|
||||
*
|
||||
* @since C++23
|
||||
*/
|
||||
template<__detail::__container_compatible_range<_Tp> _Rg>
|
||||
iterator
|
||||
insert_range(const_iterator __position, _Rg&& __rg)
|
||||
{
|
||||
list __tmp(from_range, std::forward<_Rg>(__rg), get_allocator());
|
||||
if (!__tmp.empty())
|
||||
{
|
||||
auto __it = __tmp.begin();
|
||||
splice(__position, __tmp);
|
||||
return __it;
|
||||
}
|
||||
return __position._M_const_cast();
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Remove element at given position.
|
||||
* @param __position Iterator pointing to element to be erased.
|
||||
@ -2102,6 +2223,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
||||
typename = _RequireAllocator<_Allocator>>
|
||||
list(_InputIterator, _InputIterator, _Allocator = _Allocator())
|
||||
-> list<_ValT, _Allocator>;
|
||||
|
||||
#if __glibcxx_ranges_to_container // C++ >= 23
|
||||
template<ranges::input_range _Rg,
|
||||
typename _Allocator = allocator<ranges::range_value_t<_Rg>>>
|
||||
list(from_range_t, _Rg&&, _Allocator = _Allocator())
|
||||
-> list<ranges::range_value_t<_Rg>, _Allocator>;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_CXX11
|
||||
|
@ -267,6 +267,13 @@ namespace __debug
|
||||
__gnu_debug::__base(__last), __al)
|
||||
{ }
|
||||
|
||||
#if __glibcxx_ranges_to_container // C++ >= 23
|
||||
template<__detail::__container_compatible_range<_Tp> _Rg>
|
||||
forward_list(from_range_t, _Rg&& __rg, const _Alloc& __a = _Alloc())
|
||||
: _Base(std::from_range, std::forward<_Rg>(__rg), __a)
|
||||
{ }
|
||||
#endif
|
||||
|
||||
forward_list(const forward_list&) = default;
|
||||
|
||||
forward_list(forward_list&&) = default;
|
||||
@ -311,6 +318,39 @@ namespace __debug
|
||||
this->_M_invalidate_all();
|
||||
}
|
||||
|
||||
#if __glibcxx_ranges_to_container // C++ >= 23
|
||||
template<__detail::__container_compatible_range<_Tp> _Rg>
|
||||
void
|
||||
assign_range(_Rg&& __rg)
|
||||
{
|
||||
// Have to reimplement this function, so that we use the debug
|
||||
// version of erase_after, which invalidates the correct iterators.
|
||||
|
||||
static_assert(assignable_from<_Tp&, ranges::range_reference_t<_Rg>>);
|
||||
|
||||
auto __first = ranges::begin(__rg);
|
||||
const auto __last = ranges::end(__rg);
|
||||
auto __prev = _Base::before_begin();
|
||||
auto __curr = _Base::begin();
|
||||
const auto __end = _Base::end();
|
||||
|
||||
while (__curr != __end && __first != __last)
|
||||
{
|
||||
*__curr = *__first;
|
||||
__prev = __curr;
|
||||
++__first;
|
||||
++__curr;
|
||||
}
|
||||
|
||||
if (__curr != __end)
|
||||
erase_after(const_iterator(__prev, this), end());
|
||||
else
|
||||
_Base::insert_range_after(__prev,
|
||||
ranges::subrange(std::move(__first),
|
||||
__last));
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
assign(size_type __n, const _Tp& __val)
|
||||
{
|
||||
@ -400,6 +440,10 @@ namespace __debug
|
||||
using _Base::emplace_front;
|
||||
using _Base::push_front;
|
||||
|
||||
#if __glibcxx_ranges_to_container // C++ >= 23
|
||||
using _Base::prepend_range;
|
||||
#endif
|
||||
|
||||
void
|
||||
pop_front()
|
||||
{
|
||||
@ -468,6 +512,18 @@ namespace __debug
|
||||
return { _Base::insert_after(__pos.base(), __il), this };
|
||||
}
|
||||
|
||||
#if __glibcxx_ranges_to_container // C++ >= 23
|
||||
template<__detail::__container_compatible_range<_Tp> _Rg>
|
||||
iterator
|
||||
insert_range_after(const_iterator __position, _Rg&& __rg)
|
||||
{
|
||||
auto __ret
|
||||
= _Base::insert_range_after(__position.base(),
|
||||
std::forward<_Rg>(__rg));
|
||||
return { __ret, this };
|
||||
}
|
||||
#endif
|
||||
|
||||
iterator
|
||||
erase_after(const_iterator __pos)
|
||||
{
|
||||
@ -860,6 +916,13 @@ namespace __debug
|
||||
typename = _RequireAllocator<_Allocator>>
|
||||
forward_list(size_t, _Tp, _Allocator = _Allocator())
|
||||
-> forward_list<_Tp, _Allocator>;
|
||||
|
||||
#if __glibcxx_ranges_to_container // C++ >= 23
|
||||
template<ranges::input_range _Rg,
|
||||
typename _Allocator = allocator<ranges::range_value_t<_Rg>>>
|
||||
forward_list(from_range_t, _Rg&&, _Allocator = _Allocator())
|
||||
-> forward_list<ranges::range_value_t<_Rg>, _Allocator>;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
template<typename _Tp, typename _Alloc>
|
||||
|
@ -160,6 +160,13 @@ namespace __debug
|
||||
__gnu_debug::__base(__last), __a)
|
||||
{ }
|
||||
|
||||
#if __glibcxx_ranges_to_container // C++ >= 23
|
||||
template<__detail::__container_compatible_range<_Tp> _Rg>
|
||||
list(from_range_t, _Rg&& __rg, const _Allocator& __a = _Allocator())
|
||||
: _Base(std::from_range, std::forward<_Rg>(__rg), __a)
|
||||
{ }
|
||||
#endif
|
||||
|
||||
list(_Base_ref __x)
|
||||
: _Base(__x._M_ref) { }
|
||||
|
||||
@ -207,6 +214,32 @@ namespace __debug
|
||||
this->_M_invalidate_all();
|
||||
}
|
||||
|
||||
#if __glibcxx_ranges_to_container // C++ >= 23
|
||||
template<__detail::__container_compatible_range<_Tp> _Rg>
|
||||
void
|
||||
assign_range(_Rg&& __rg)
|
||||
{
|
||||
// Have to reimplement this function, so that we use the debug
|
||||
// version of erase, which invalidates the correct iterators.
|
||||
|
||||
static_assert(assignable_from<_Tp&, ranges::range_reference_t<_Rg>>);
|
||||
|
||||
auto __first1 = _Base::begin();
|
||||
const auto __last1 = _Base::end();
|
||||
auto __first2 = ranges::begin(__rg);
|
||||
const auto __last2 = ranges::end(__rg);
|
||||
for (; __first1 != __last1 && __first2 != __last2;
|
||||
++__first1, (void)++__first2)
|
||||
*__first1 = *__first2;
|
||||
if (__first2 == __last2)
|
||||
erase(const_iterator(__first1, this),
|
||||
const_iterator(__last1, this));
|
||||
else
|
||||
_Base::insert_range(__last1,
|
||||
ranges::subrange(std::move(__first2), __last2));
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
assign(size_type __n, const _Tp& __t)
|
||||
{
|
||||
@ -401,6 +434,11 @@ namespace __debug
|
||||
using _Base::emplace_front;
|
||||
#endif
|
||||
|
||||
#if __glibcxx_ranges_to_container // C++ >= 23
|
||||
using _Base::prepend_range;
|
||||
using _Base::append_range;
|
||||
#endif
|
||||
|
||||
void
|
||||
pop_front() _GLIBCXX_NOEXCEPT
|
||||
{
|
||||
@ -511,6 +549,17 @@ namespace __debug
|
||||
}
|
||||
#endif
|
||||
|
||||
#if __glibcxx_ranges_to_container // C++ >= 23
|
||||
template<__detail::__container_compatible_range<_Tp> _Rg>
|
||||
iterator
|
||||
insert_range(const_iterator __position, _Rg&& __rg)
|
||||
{
|
||||
auto __ret = _Base::insert_range(__position.base(),
|
||||
std::forward<_Rg>(__rg));
|
||||
return { __ret, this };
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
_Base_iterator
|
||||
#if __cplusplus >= 201103L
|
||||
@ -920,6 +969,13 @@ namespace __debug
|
||||
typename = _RequireAllocator<_Allocator>>
|
||||
list(size_t, _Tp, _Allocator = _Allocator())
|
||||
-> list<_Tp, _Allocator>;
|
||||
|
||||
#if __glibcxx_ranges_to_container // C++ >= 23
|
||||
template<ranges::input_range _Rg,
|
||||
typename _Allocator = allocator<ranges::range_value_t<_Rg>>>
|
||||
list(from_range_t, _Rg&&, _Allocator = _Allocator())
|
||||
-> list<ranges::range_value_t<_Rg>, _Allocator>;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
template<typename _Tp, typename _Alloc>
|
||||
|
@ -0,0 +1,100 @@
|
||||
// { dg-do run { target c++23 } }
|
||||
|
||||
#include <forward_list>
|
||||
#include <span>
|
||||
#include <testsuite_hooks.h>
|
||||
#include <testsuite_iterators.h>
|
||||
#include <testsuite_allocator.h>
|
||||
|
||||
void
|
||||
test_deduction_guide(long* p)
|
||||
{
|
||||
__gnu_test::test_input_range<long> r(p, p);
|
||||
std::forward_list v(std::from_range, r);
|
||||
static_assert(std::is_same_v<decltype(v), std::forward_list<long>>);
|
||||
|
||||
using Alloc = __gnu_test::SimpleAllocator<long>;
|
||||
Alloc alloc;
|
||||
std::forward_list v2(std::from_range, r, alloc);
|
||||
static_assert(std::is_same_v<decltype(v2), std::forward_list<long, Alloc>>);
|
||||
}
|
||||
|
||||
template<typename Range, typename Alloc>
|
||||
constexpr void
|
||||
do_test(Alloc alloc)
|
||||
{
|
||||
// The forward_list's value_type.
|
||||
using V = typename std::allocator_traits<Alloc>::value_type;
|
||||
|
||||
// The range's value_type.
|
||||
using T = std::ranges::range_value_t<Range>;
|
||||
T a[]{1,2,3,4,5,6,7,8,9};
|
||||
|
||||
auto eq = [](const std::forward_list<V, Alloc>& l, std::span<T> r) {
|
||||
if (std::distance(l.begin(), l.end()) != r.size())
|
||||
return false;
|
||||
unsigned i = 0;
|
||||
for (auto& e : l)
|
||||
if (e != r[i++])
|
||||
return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
std::forward_list<V, Alloc> v0(std::from_range, Range(a, a+0));
|
||||
VERIFY( v0.empty() );
|
||||
VERIFY( v0.get_allocator() == Alloc() );
|
||||
|
||||
std::forward_list<V, Alloc> v4(std::from_range, Range(a, a+4));
|
||||
VERIFY( eq(v4, {a, 4}) );
|
||||
VERIFY( v4.get_allocator() == Alloc() );
|
||||
|
||||
std::forward_list<V, Alloc> v9(std::from_range, Range(a, a+9), alloc);
|
||||
VERIFY( eq(v9, {a, 9}) );
|
||||
VERIFY( v9.get_allocator() == alloc );
|
||||
}
|
||||
|
||||
template<typename Range>
|
||||
void
|
||||
do_test_a()
|
||||
{
|
||||
do_test<Range>(std::allocator<int>());
|
||||
do_test<Range>(__gnu_test::uneq_allocator<int>(42));
|
||||
}
|
||||
|
||||
bool
|
||||
test_ranges()
|
||||
{
|
||||
using namespace __gnu_test;
|
||||
|
||||
do_test_a<test_forward_range<int>>();
|
||||
do_test_a<test_forward_sized_range<int>>();
|
||||
do_test_a<test_sized_range_sized_sent<int, forward_iterator_wrapper>>();
|
||||
|
||||
do_test_a<test_input_range<int>>();
|
||||
do_test_a<test_input_sized_range<int>>();
|
||||
do_test_a<test_sized_range_sized_sent<int, input_iterator_wrapper>>();
|
||||
|
||||
do_test_a<test_range<int, input_iterator_wrapper_nocopy>>();
|
||||
do_test_a<test_sized_range<int, input_iterator_wrapper_nocopy>>();
|
||||
do_test_a<test_sized_range_sized_sent<int, input_iterator_wrapper_nocopy>>();
|
||||
|
||||
do_test_a<test_forward_range<short>>();
|
||||
do_test_a<test_input_range<short>>();
|
||||
|
||||
// Not lvalue-convertible to bool
|
||||
struct C {
|
||||
C(int v) : val(v) { }
|
||||
operator int() && { return val; }
|
||||
bool operator==(int b) const { return b == val; }
|
||||
int val;
|
||||
};
|
||||
using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
|
||||
do_test<rvalue_input_range>(std::allocator<int>());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_ranges();
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
// { dg-do run { target c++23 } }
|
||||
|
||||
#include <forward_list>
|
||||
#include <span>
|
||||
#include <testsuite_hooks.h>
|
||||
#include <testsuite_iterators.h>
|
||||
#include <testsuite_allocator.h>
|
||||
|
||||
template<typename Range, typename Alloc>
|
||||
constexpr void
|
||||
do_test()
|
||||
{
|
||||
// The forward_list's value_type.
|
||||
using V = typename std::allocator_traits<Alloc>::value_type;
|
||||
|
||||
// The range's value_type.
|
||||
using T = std::ranges::range_value_t<Range>;
|
||||
T a[]{1,2,3,4,5,6,7,8,9};
|
||||
|
||||
auto eq = [](const std::forward_list<V, Alloc>& l, std::span<T> r) {
|
||||
if (std::distance(l.begin(), l.end()) != r.size())
|
||||
return false;
|
||||
unsigned i = 0;
|
||||
for (auto& e : l)
|
||||
if (e != r[i++])
|
||||
return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
// assign to empty forward_list
|
||||
std::forward_list<V, Alloc> v;
|
||||
v.assign_range(Range(a, a));
|
||||
VERIFY( v.empty() );
|
||||
v.assign_range(Range(a, a+4));
|
||||
VERIFY( eq(v, {a, 4}) );
|
||||
v.clear();
|
||||
v.assign_range(Range(a));
|
||||
VERIFY( eq(v, a) );
|
||||
|
||||
// assign to non-empty forward_list
|
||||
v.assign_range(Range(a, a+4));
|
||||
VERIFY( eq(v, {a, 4}) );
|
||||
v.assign_range(Range(a)); // larger than size()
|
||||
VERIFY( eq(v, a) );
|
||||
v.assign_range(Range(a, a+4)); // smaller than size()
|
||||
VERIFY( eq(v, {a, 4}) );
|
||||
v.assign_range(Range(a+2, a+6)); // equal to size()
|
||||
VERIFY( eq(v, {a+2, 4}) );
|
||||
v.assign_range(Range(a, a));
|
||||
VERIFY( v.empty() );
|
||||
}
|
||||
|
||||
template<typename Range>
|
||||
void
|
||||
do_test_a()
|
||||
{
|
||||
do_test<Range, std::allocator<int>>();
|
||||
do_test<Range, __gnu_test::SimpleAllocator<int>>();
|
||||
}
|
||||
|
||||
bool
|
||||
test_ranges()
|
||||
{
|
||||
using namespace __gnu_test;
|
||||
|
||||
do_test_a<test_forward_range<int>>();
|
||||
do_test_a<test_forward_sized_range<int>>();
|
||||
do_test_a<test_sized_range_sized_sent<int, forward_iterator_wrapper>>();
|
||||
|
||||
do_test_a<test_input_range<int>>();
|
||||
do_test_a<test_input_sized_range<int>>();
|
||||
do_test_a<test_sized_range_sized_sent<int, input_iterator_wrapper>>();
|
||||
|
||||
do_test_a<test_range<int, input_iterator_wrapper_nocopy>>();
|
||||
do_test_a<test_sized_range<int, input_iterator_wrapper_nocopy>>();
|
||||
do_test_a<test_sized_range_sized_sent<int, input_iterator_wrapper_nocopy>>();
|
||||
|
||||
do_test_a<test_forward_range<short>>();
|
||||
do_test_a<test_input_range<short>>();
|
||||
|
||||
// Not lvalue-convertible to int
|
||||
struct C {
|
||||
C(int v) : val(v) { }
|
||||
operator int() && { return val; }
|
||||
bool operator==(int b) const { return b == val; }
|
||||
int val;
|
||||
};
|
||||
using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
|
||||
do_test<rvalue_input_range, std::allocator<int>>();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_ranges();
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
// { dg-do run { target c++23 } }
|
||||
|
||||
#include <forward_list>
|
||||
#include <span>
|
||||
#include <testsuite_hooks.h>
|
||||
#include <testsuite_iterators.h>
|
||||
#include <testsuite_allocator.h>
|
||||
|
||||
template<typename Range, typename Alloc>
|
||||
constexpr void
|
||||
do_test()
|
||||
{
|
||||
// The forward_list's value_type.
|
||||
using V = typename std::allocator_traits<Alloc>::value_type;
|
||||
|
||||
// The range's value_type.
|
||||
using T = std::ranges::range_value_t<Range>;
|
||||
T a[]{1,2,3,4,5,6,7,8,9};
|
||||
|
||||
auto eq = [](const std::forward_list<V, Alloc>& l, std::span<T> r) {
|
||||
if (std::distance(l.begin(), l.end()) != r.size())
|
||||
return false;
|
||||
unsigned i = 0;
|
||||
for (auto& e : l)
|
||||
if (e != r[i++])
|
||||
return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
std::forward_list<V, Alloc> v;
|
||||
v.insert_range_after(v.before_begin(), Range(a, a));
|
||||
VERIFY( v.empty() );
|
||||
v.insert_range_after(v.before_begin(), Range(a, a+4));
|
||||
VERIFY( eq(v, {a, a+4}) );
|
||||
v.clear();
|
||||
v.insert_range_after(v.before_begin(), Range(a+4, a+9));
|
||||
VERIFY( eq(v, {a+4, a+9}) );
|
||||
v.insert_range_after(v.before_begin(), Range(a, a+4));
|
||||
VERIFY( eq(v, a) );
|
||||
v.clear();
|
||||
v.insert_range_after(v.before_begin(), Range(a, a+3));
|
||||
v.insert_range_after(std::next(v.before_begin(), 3), Range(a+6, a+9));
|
||||
v.insert_range_after(std::next(v.before_begin(), 3), Range(a+3, a+6));
|
||||
VERIFY( eq(v, a) );
|
||||
v.insert_range_after(std::next(v.before_begin(), 2), Range(a, a));
|
||||
VERIFY( eq(v, a) );
|
||||
}
|
||||
|
||||
template<typename Range>
|
||||
void
|
||||
do_test_a()
|
||||
{
|
||||
do_test<Range, std::allocator<int>>();
|
||||
do_test<Range, __gnu_test::SimpleAllocator<int>>();
|
||||
}
|
||||
|
||||
bool
|
||||
test_ranges()
|
||||
{
|
||||
using namespace __gnu_test;
|
||||
|
||||
do_test_a<test_forward_range<int>>();
|
||||
do_test_a<test_forward_sized_range<int>>();
|
||||
do_test_a<test_sized_range_sized_sent<int, forward_iterator_wrapper>>();
|
||||
|
||||
do_test_a<test_input_range<int>>();
|
||||
do_test_a<test_input_sized_range<int>>();
|
||||
do_test_a<test_sized_range_sized_sent<int, input_iterator_wrapper>>();
|
||||
|
||||
do_test_a<test_range<int, input_iterator_wrapper_nocopy>>();
|
||||
do_test_a<test_sized_range<int, input_iterator_wrapper_nocopy>>();
|
||||
do_test_a<test_sized_range_sized_sent<int, input_iterator_wrapper_nocopy>>();
|
||||
|
||||
do_test_a<test_forward_range<short>>();
|
||||
do_test_a<test_input_range<short>>();
|
||||
|
||||
// Not lvalue-convertible to int
|
||||
struct C {
|
||||
C(int v) : val(v) { }
|
||||
operator int() && { return val; }
|
||||
bool operator==(int b) const { return b == val; }
|
||||
int val;
|
||||
};
|
||||
using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
|
||||
do_test<rvalue_input_range, std::allocator<int>>();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_ranges();
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
// { dg-do run { target c++23 } }
|
||||
|
||||
#include <forward_list>
|
||||
#include <span>
|
||||
#include <testsuite_hooks.h>
|
||||
#include <testsuite_iterators.h>
|
||||
#include <testsuite_allocator.h>
|
||||
|
||||
template<typename Range, typename Alloc>
|
||||
constexpr void
|
||||
do_test()
|
||||
{
|
||||
// The forward_list's value_type.
|
||||
using V = typename std::allocator_traits<Alloc>::value_type;
|
||||
|
||||
// The range's value_type.
|
||||
using T = std::ranges::range_value_t<Range>;
|
||||
T a[]{1,2,3,4,5,6,7,8,9};
|
||||
|
||||
auto eq = [](const std::forward_list<V, Alloc>& l, std::span<T> r) {
|
||||
if (std::distance(l.begin(), l.end()) != r.size())
|
||||
return false;
|
||||
unsigned i = 0;
|
||||
for (auto& e : l)
|
||||
if (e != r[i++])
|
||||
return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
std::forward_list<V, Alloc> v;
|
||||
v.prepend_range(Range(a+4, a+9));
|
||||
VERIFY( eq(v, {a+4, 5}) );
|
||||
v.prepend_range(Range(a, a+4));
|
||||
VERIFY( eq(v, a) );
|
||||
v.prepend_range(Range(a, a));
|
||||
VERIFY( eq(v, a) );
|
||||
v.clear();
|
||||
v.prepend_range(Range(a, a));
|
||||
VERIFY( v.empty() );
|
||||
}
|
||||
|
||||
template<typename Range>
|
||||
void
|
||||
do_test_a()
|
||||
{
|
||||
do_test<Range, std::allocator<int>>();
|
||||
do_test<Range, __gnu_test::SimpleAllocator<int>>();
|
||||
}
|
||||
|
||||
bool
|
||||
test_ranges()
|
||||
{
|
||||
using namespace __gnu_test;
|
||||
|
||||
do_test_a<test_forward_range<int>>();
|
||||
do_test_a<test_forward_sized_range<int>>();
|
||||
do_test_a<test_sized_range_sized_sent<int, forward_iterator_wrapper>>();
|
||||
|
||||
do_test_a<test_input_range<int>>();
|
||||
do_test_a<test_input_sized_range<int>>();
|
||||
do_test_a<test_sized_range_sized_sent<int, input_iterator_wrapper>>();
|
||||
|
||||
do_test_a<test_range<int, input_iterator_wrapper_nocopy>>();
|
||||
do_test_a<test_sized_range<int, input_iterator_wrapper_nocopy>>();
|
||||
do_test_a<test_sized_range_sized_sent<int, input_iterator_wrapper_nocopy>>();
|
||||
|
||||
do_test_a<test_forward_range<short>>();
|
||||
do_test_a<test_input_range<short>>();
|
||||
|
||||
// Not lvalue-convertible to int
|
||||
struct C {
|
||||
C(int v) : val(v) { }
|
||||
operator int() && { return val; }
|
||||
bool operator==(int b) const { return b == val; }
|
||||
int val;
|
||||
};
|
||||
using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
|
||||
do_test<rvalue_input_range, std::allocator<int>>();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_ranges();
|
||||
}
|
100
libstdc++-v3/testsuite/23_containers/list/cons/from_range.cc
Normal file
100
libstdc++-v3/testsuite/23_containers/list/cons/from_range.cc
Normal file
@ -0,0 +1,100 @@
|
||||
// { dg-do run { target c++23 } }
|
||||
|
||||
#include <list>
|
||||
#include <span>
|
||||
#include <testsuite_hooks.h>
|
||||
#include <testsuite_iterators.h>
|
||||
#include <testsuite_allocator.h>
|
||||
|
||||
void
|
||||
test_deduction_guide(long* p)
|
||||
{
|
||||
__gnu_test::test_input_range<long> r(p, p);
|
||||
std::list v(std::from_range, r);
|
||||
static_assert(std::is_same_v<decltype(v), std::list<long>>);
|
||||
|
||||
using Alloc = __gnu_test::SimpleAllocator<long>;
|
||||
Alloc alloc;
|
||||
std::list v2(std::from_range, r, alloc);
|
||||
static_assert(std::is_same_v<decltype(v2), std::list<long, Alloc>>);
|
||||
}
|
||||
|
||||
template<typename Range, typename Alloc>
|
||||
constexpr void
|
||||
do_test(Alloc alloc)
|
||||
{
|
||||
// The list's value_type.
|
||||
using V = typename std::allocator_traits<Alloc>::value_type;
|
||||
|
||||
// The range's value_type.
|
||||
using T = std::ranges::range_value_t<Range>;
|
||||
T a[]{1,2,3,4,5,6,7,8,9};
|
||||
|
||||
auto eq = [](const std::list<V, Alloc>& l, std::span<T> r) {
|
||||
if (l.size() != r.size())
|
||||
return false;
|
||||
unsigned i = 0;
|
||||
for (auto& e : l)
|
||||
if (e != r[i++])
|
||||
return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
std::list<V, Alloc> v0(std::from_range, Range(a, a+0));
|
||||
VERIFY( v0.empty() );
|
||||
VERIFY( v0.get_allocator() == Alloc() );
|
||||
|
||||
std::list<V, Alloc> v4(std::from_range, Range(a, a+4));
|
||||
VERIFY( eq(v4, {a, 4}) );
|
||||
VERIFY( v4.get_allocator() == Alloc() );
|
||||
|
||||
std::list<V, Alloc> v9(std::from_range, Range(a, a+9), alloc);
|
||||
VERIFY( eq(v9, {a, 9}) );
|
||||
VERIFY( v9.get_allocator() == alloc );
|
||||
}
|
||||
|
||||
template<typename Range>
|
||||
void
|
||||
do_test_a()
|
||||
{
|
||||
do_test<Range>(std::allocator<int>());
|
||||
do_test<Range>(__gnu_test::uneq_allocator<int>(42));
|
||||
}
|
||||
|
||||
bool
|
||||
test_ranges()
|
||||
{
|
||||
using namespace __gnu_test;
|
||||
|
||||
do_test_a<test_forward_range<int>>();
|
||||
do_test_a<test_forward_sized_range<int>>();
|
||||
do_test_a<test_sized_range_sized_sent<int, forward_iterator_wrapper>>();
|
||||
|
||||
do_test_a<test_input_range<int>>();
|
||||
do_test_a<test_input_sized_range<int>>();
|
||||
do_test_a<test_sized_range_sized_sent<int, input_iterator_wrapper>>();
|
||||
|
||||
do_test_a<test_range<int, input_iterator_wrapper_nocopy>>();
|
||||
do_test_a<test_sized_range<int, input_iterator_wrapper_nocopy>>();
|
||||
do_test_a<test_sized_range_sized_sent<int, input_iterator_wrapper_nocopy>>();
|
||||
|
||||
do_test_a<test_forward_range<short>>();
|
||||
do_test_a<test_input_range<short>>();
|
||||
|
||||
// Not lvalue-convertible to bool
|
||||
struct C {
|
||||
C(int v) : val(v) { }
|
||||
operator int() && { return val; }
|
||||
bool operator==(int b) const { return b == val; }
|
||||
int val;
|
||||
};
|
||||
using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
|
||||
do_test<rvalue_input_range>(std::allocator<int>());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_ranges();
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
// { dg-do run { target c++23 } }
|
||||
|
||||
#include <list>
|
||||
#include <span>
|
||||
#include <testsuite_hooks.h>
|
||||
#include <testsuite_iterators.h>
|
||||
#include <testsuite_allocator.h>
|
||||
|
||||
template<typename Range, typename Alloc>
|
||||
constexpr void
|
||||
do_test()
|
||||
{
|
||||
// The list's value_type.
|
||||
using V = typename std::allocator_traits<Alloc>::value_type;
|
||||
|
||||
// The range's value_type.
|
||||
using T = std::ranges::range_value_t<Range>;
|
||||
T a[]{1,2,3,4,5,6,7,8,9};
|
||||
|
||||
auto eq = [](const std::list<V, Alloc>& l, std::span<T> r) {
|
||||
if (l.size() != r.size())
|
||||
return false;
|
||||
unsigned i = 0;
|
||||
for (auto& e : l)
|
||||
if (e != r[i++])
|
||||
return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
std::list<V, Alloc> v;
|
||||
v.append_range(Range(a, a+4));
|
||||
VERIFY( eq(v, {a, 4}) );
|
||||
v.append_range(Range(a+4, a+9));
|
||||
VERIFY( eq(v, a) );
|
||||
v.append_range(Range(a, a));
|
||||
VERIFY( eq(v, a) );
|
||||
v.clear();
|
||||
v.append_range(Range(a, a));
|
||||
VERIFY( v.empty() );
|
||||
}
|
||||
|
||||
template<typename Range>
|
||||
void
|
||||
do_test_a()
|
||||
{
|
||||
do_test<Range, std::allocator<int>>();
|
||||
do_test<Range, __gnu_test::SimpleAllocator<int>>();
|
||||
}
|
||||
|
||||
bool
|
||||
test_ranges()
|
||||
{
|
||||
using namespace __gnu_test;
|
||||
|
||||
do_test_a<test_forward_range<int>>();
|
||||
do_test_a<test_forward_sized_range<int>>();
|
||||
do_test_a<test_sized_range_sized_sent<int, forward_iterator_wrapper>>();
|
||||
|
||||
do_test_a<test_input_range<int>>();
|
||||
do_test_a<test_input_sized_range<int>>();
|
||||
do_test_a<test_sized_range_sized_sent<int, input_iterator_wrapper>>();
|
||||
|
||||
do_test_a<test_range<int, input_iterator_wrapper_nocopy>>();
|
||||
do_test_a<test_sized_range<int, input_iterator_wrapper_nocopy>>();
|
||||
do_test_a<test_sized_range_sized_sent<int, input_iterator_wrapper_nocopy>>();
|
||||
|
||||
do_test_a<test_forward_range<short>>();
|
||||
do_test_a<test_input_range<short>>();
|
||||
|
||||
// Not lvalue-convertible to int
|
||||
struct C {
|
||||
C(int v) : val(v) { }
|
||||
operator int() && { return val; }
|
||||
bool operator==(int b) const { return b == val; }
|
||||
int val;
|
||||
};
|
||||
using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
|
||||
do_test<rvalue_input_range, std::allocator<int>>();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_ranges();
|
||||
}
|
@ -0,0 +1,99 @@
|
||||
// { dg-do run { target c++23 } }
|
||||
|
||||
#include <list>
|
||||
#include <span>
|
||||
#include <testsuite_hooks.h>
|
||||
#include <testsuite_iterators.h>
|
||||
#include <testsuite_allocator.h>
|
||||
|
||||
template<typename Range, typename Alloc>
|
||||
constexpr void
|
||||
do_test()
|
||||
{
|
||||
// The list's value_type.
|
||||
using V = typename std::allocator_traits<Alloc>::value_type;
|
||||
|
||||
// The range's value_type.
|
||||
using T = std::ranges::range_value_t<Range>;
|
||||
T a[]{1,2,3,4,5,6,7,8,9};
|
||||
|
||||
auto eq = [](const std::list<V, Alloc>& l, std::span<T> r) {
|
||||
if (l.size() != r.size())
|
||||
return false;
|
||||
unsigned i = 0;
|
||||
for (auto& e : l)
|
||||
if (e != r[i++])
|
||||
return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
// assign to empty list
|
||||
std::list<V, Alloc> v;
|
||||
v.assign_range(Range(a, a));
|
||||
VERIFY( v.empty() );
|
||||
v.assign_range(Range(a, a+4));
|
||||
VERIFY( eq(v, {a, 4}) );
|
||||
v.clear();
|
||||
v.assign_range(Range(a));
|
||||
VERIFY( eq(v, a) );
|
||||
|
||||
// assign to non-empty list
|
||||
v.assign_range(Range(a, a+4));
|
||||
VERIFY( eq(v, {a, 4}) );
|
||||
v.assign_range(Range(a)); // larger than size()
|
||||
VERIFY( eq(v, a) );
|
||||
v.assign_range(Range(a, a+4)); // smaller than size()
|
||||
VERIFY( eq(v, {a, 4}) );
|
||||
v.clear();
|
||||
v.resize(4);
|
||||
v.assign_range(Range(a, a+4)); // equal to size()
|
||||
VERIFY( eq(v, {a, 4}) );
|
||||
v.assign_range(Range(a, a));
|
||||
VERIFY( v.empty() );
|
||||
}
|
||||
|
||||
template<typename Range>
|
||||
void
|
||||
do_test_a()
|
||||
{
|
||||
do_test<Range, std::allocator<int>>();
|
||||
do_test<Range, __gnu_test::SimpleAllocator<int>>();
|
||||
}
|
||||
|
||||
bool
|
||||
test_ranges()
|
||||
{
|
||||
using namespace __gnu_test;
|
||||
|
||||
do_test_a<test_forward_range<int>>();
|
||||
do_test_a<test_forward_sized_range<int>>();
|
||||
do_test_a<test_sized_range_sized_sent<int, forward_iterator_wrapper>>();
|
||||
|
||||
do_test_a<test_input_range<int>>();
|
||||
do_test_a<test_input_sized_range<int>>();
|
||||
do_test_a<test_sized_range_sized_sent<int, input_iterator_wrapper>>();
|
||||
|
||||
do_test_a<test_range<int, input_iterator_wrapper_nocopy>>();
|
||||
do_test_a<test_sized_range<int, input_iterator_wrapper_nocopy>>();
|
||||
do_test_a<test_sized_range_sized_sent<int, input_iterator_wrapper_nocopy>>();
|
||||
|
||||
do_test_a<test_forward_range<short>>();
|
||||
do_test_a<test_input_range<short>>();
|
||||
|
||||
// Not lvalue-convertible to int
|
||||
struct C {
|
||||
C(int v) : val(v) { }
|
||||
operator int() && { return val; }
|
||||
bool operator==(int b) const { return b == val; }
|
||||
int val;
|
||||
};
|
||||
using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
|
||||
do_test<rvalue_input_range, std::allocator<int>>();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_ranges();
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
// { dg-do run { target c++23 } }
|
||||
|
||||
#include <list>
|
||||
#include <span>
|
||||
#include <testsuite_hooks.h>
|
||||
#include <testsuite_iterators.h>
|
||||
#include <testsuite_allocator.h>
|
||||
|
||||
template<typename Range, typename Alloc>
|
||||
constexpr void
|
||||
do_test()
|
||||
{
|
||||
// The list's value_type.
|
||||
using V = typename std::allocator_traits<Alloc>::value_type;
|
||||
|
||||
// The range's value_type.
|
||||
using T = std::ranges::range_value_t<Range>;
|
||||
T a[]{1,2,3,4,5,6,7,8,9};
|
||||
|
||||
auto eq = [](const std::list<V, Alloc>& l, std::span<T> r) {
|
||||
if (l.size() != r.size())
|
||||
return false;
|
||||
unsigned i = 0;
|
||||
for (auto& e : l)
|
||||
if (e != r[i++])
|
||||
return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
std::list<V, Alloc> v;
|
||||
v.insert_range(v.begin(), Range(a, a));
|
||||
VERIFY( v.empty() );
|
||||
v.insert_range(v.begin(), Range(a, a+4));
|
||||
VERIFY( eq(v, {a, a+4}) );
|
||||
v.clear();
|
||||
v.insert_range(v.begin(), Range(a+4, a+9));
|
||||
VERIFY( eq(v, {a+4, a+9}) );
|
||||
v.insert_range(v.begin(), Range(a, a+4));
|
||||
VERIFY( eq(v, a) );
|
||||
v.clear();
|
||||
v.insert_range(v.begin(), Range(a, a+3));
|
||||
v.insert_range(v.end(), Range(a+6, a+9));
|
||||
v.insert_range(std::next(v.begin(), 3), Range(a+3, a+6));
|
||||
VERIFY( eq(v, a) );
|
||||
v.resize(3);
|
||||
v.insert_range(std::next(v.begin()), Range(a+4, a+9));
|
||||
v.insert_range(std::next(v.begin()), Range(a+1, a+4));
|
||||
v.resize(9);
|
||||
VERIFY( eq(v, a) );
|
||||
v.insert_range(std::next(v.begin(), 6), Range(a, a));
|
||||
VERIFY( eq(v, a) );
|
||||
}
|
||||
|
||||
template<typename Range>
|
||||
void
|
||||
do_test_a()
|
||||
{
|
||||
do_test<Range, std::allocator<int>>();
|
||||
do_test<Range, __gnu_test::SimpleAllocator<int>>();
|
||||
}
|
||||
|
||||
bool
|
||||
test_ranges()
|
||||
{
|
||||
using namespace __gnu_test;
|
||||
|
||||
do_test_a<test_forward_range<int>>();
|
||||
do_test_a<test_forward_sized_range<int>>();
|
||||
do_test_a<test_sized_range_sized_sent<int, forward_iterator_wrapper>>();
|
||||
|
||||
do_test_a<test_input_range<int>>();
|
||||
do_test_a<test_input_sized_range<int>>();
|
||||
do_test_a<test_sized_range_sized_sent<int, input_iterator_wrapper>>();
|
||||
|
||||
do_test_a<test_range<int, input_iterator_wrapper_nocopy>>();
|
||||
do_test_a<test_sized_range<int, input_iterator_wrapper_nocopy>>();
|
||||
do_test_a<test_sized_range_sized_sent<int, input_iterator_wrapper_nocopy>>();
|
||||
|
||||
do_test_a<test_forward_range<short>>();
|
||||
do_test_a<test_input_range<short>>();
|
||||
|
||||
// Not lvalue-convertible to int
|
||||
struct C {
|
||||
C(int v) : val(v) { }
|
||||
operator int() && { return val; }
|
||||
bool operator==(int b) const { return b == val; }
|
||||
int val;
|
||||
};
|
||||
using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
|
||||
do_test<rvalue_input_range, std::allocator<int>>();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_ranges();
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
// { dg-do run { target c++23 } }
|
||||
|
||||
#include <list>
|
||||
#include <span>
|
||||
#include <testsuite_hooks.h>
|
||||
#include <testsuite_iterators.h>
|
||||
#include <testsuite_allocator.h>
|
||||
|
||||
template<typename Range, typename Alloc>
|
||||
constexpr void
|
||||
do_test()
|
||||
{
|
||||
// The list's value_type.
|
||||
using V = typename std::allocator_traits<Alloc>::value_type;
|
||||
|
||||
// The range's value_type.
|
||||
using T = std::ranges::range_value_t<Range>;
|
||||
T a[]{1,2,3,4,5,6,7,8,9};
|
||||
|
||||
auto eq = [](const std::list<V, Alloc>& l, std::span<T> r) {
|
||||
if (l.size() != r.size())
|
||||
return false;
|
||||
unsigned i = 0;
|
||||
for (auto& e : l)
|
||||
if (e != r[i++])
|
||||
return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
std::list<V, Alloc> v;
|
||||
v.prepend_range(Range(a+4, a+9));
|
||||
VERIFY( eq(v, {a+4, 5}) );
|
||||
v.prepend_range(Range(a, a+4));
|
||||
VERIFY( eq(v, a) );
|
||||
v.prepend_range(Range(a, a));
|
||||
VERIFY( eq(v, a) );
|
||||
v.clear();
|
||||
v.prepend_range(Range(a, a));
|
||||
VERIFY( v.empty() );
|
||||
}
|
||||
|
||||
template<typename Range>
|
||||
void
|
||||
do_test_a()
|
||||
{
|
||||
do_test<Range, std::allocator<int>>();
|
||||
do_test<Range, __gnu_test::SimpleAllocator<int>>();
|
||||
}
|
||||
|
||||
bool
|
||||
test_ranges()
|
||||
{
|
||||
using namespace __gnu_test;
|
||||
|
||||
do_test_a<test_forward_range<int>>();
|
||||
do_test_a<test_forward_sized_range<int>>();
|
||||
do_test_a<test_sized_range_sized_sent<int, forward_iterator_wrapper>>();
|
||||
|
||||
do_test_a<test_input_range<int>>();
|
||||
do_test_a<test_input_sized_range<int>>();
|
||||
do_test_a<test_sized_range_sized_sent<int, input_iterator_wrapper>>();
|
||||
|
||||
do_test_a<test_range<int, input_iterator_wrapper_nocopy>>();
|
||||
do_test_a<test_sized_range<int, input_iterator_wrapper_nocopy>>();
|
||||
do_test_a<test_sized_range_sized_sent<int, input_iterator_wrapper_nocopy>>();
|
||||
|
||||
do_test_a<test_forward_range<short>>();
|
||||
do_test_a<test_input_range<short>>();
|
||||
|
||||
// Not lvalue-convertible to int
|
||||
struct C {
|
||||
C(int v) : val(v) { }
|
||||
operator int() && { return val; }
|
||||
bool operator==(int b) const { return b == val; }
|
||||
int val;
|
||||
};
|
||||
using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
|
||||
do_test<rvalue_input_range, std::allocator<int>>();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_ranges();
|
||||
}
|
Loading…
Reference in New Issue
Block a user