Flatten type hierarchy for enumerated_iterator
Pass adjust_iterator_dereference_type directly, instead of passing iterator_dereference_type and letting enumerated_iterator compute adjust_iterator_dereference_type.
This commit is contained in:
parent
f38a1b95a1
commit
b1278b8e39
|
@ -59,12 +59,11 @@ typename std::remove_reference<typename std::remove_reference<T>::type::index_ty
|
|||
|
||||
}
|
||||
|
||||
template <typename range_index_type, typename range_iterator_type, typename iterator_dereference_type>
|
||||
template <typename range_index_type, typename range_iterator_type, typename adjust_iterator_dereference_type>
|
||||
class enumerated_iterator
|
||||
{
|
||||
range_iterator_type m_iter;
|
||||
range_index_type m_idx;
|
||||
using adjust_iterator_dereference_type = d_enumerate::detail::adjust_iterator_dereference_type<range_index_type, iterator_dereference_type>;
|
||||
public:
|
||||
using index_type = range_index_type;
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
|
@ -117,7 +116,7 @@ class enumerate : partial_range_t<range_iterator_type, range_index_type>
|
|||
using enumerated_iterator_type = enumerated_iterator<
|
||||
range_index_type,
|
||||
range_iterator_type,
|
||||
typename std::remove_cv<iterator_dereference_type>::type>;
|
||||
d_enumerate::detail::adjust_iterator_dereference_type<range_index_type, typename std::remove_cv<iterator_dereference_type>::type>>;
|
||||
const range_index_type m_idx;
|
||||
public:
|
||||
using range_owns_iterated_storage = std::false_type;
|
||||
|
@ -130,6 +129,11 @@ public:
|
|||
enumerate(range_type &&t, const index_type i = index_type{}) :
|
||||
base_type(std::forward<range_type>(t)), m_idx(i)
|
||||
{
|
||||
/* Block using `enumerate` on an ephemeral range, since the storage
|
||||
* owned by the range must exist until the `enumerate` object is
|
||||
* fully consumed. If `range_type &&` is an ephemeral range, then its
|
||||
* storage may cease to exist after this constructor returns.
|
||||
*/
|
||||
static_assert(!any_ephemeral_range<range_type &&>::value, "cannot enumerate storage of ephemeral ranges");
|
||||
static_assert(std::is_rvalue_reference<range_type &&>::value || std::is_lvalue_reference<iterator_dereference_type>::value, "lvalue range must produce lvalue reference enumerated_value");
|
||||
}
|
||||
|
|
|
@ -10,13 +10,25 @@
|
|||
|
||||
namespace detail {
|
||||
|
||||
/* In the general case, a range is ephemeral if `T` is an rvalue reference,
|
||||
* since an rvalue may be moved or destroyed by the end of the statement.
|
||||
*/
|
||||
template <typename T>
|
||||
std::is_rvalue_reference<T> is_ephemeral_range(...);
|
||||
|
||||
/* As a special exception to the general case, if the type T defines an inner
|
||||
* type `range_owns_iterated_storage`, delegate the test to that type. This
|
||||
* allows a type T to declare that it is only a view on longer-lived storage,
|
||||
* and therefore the storage is not ephemeral even when `T` is an rvalue
|
||||
* reference.
|
||||
*/
|
||||
template <typename T>
|
||||
typename std::remove_reference<T>::type::range_owns_iterated_storage is_ephemeral_range(std::nullptr_t);
|
||||
|
||||
}
|
||||
|
||||
/* Define a convenience helper that applies the `is_ephemeral_range` test to
|
||||
* any number of types.
|
||||
*/
|
||||
template <typename... Tn>
|
||||
using any_ephemeral_range = std::disjunction<decltype(detail::is_ephemeral_range<Tn>(nullptr))...>;
|
||||
|
|
Loading…
Reference in a new issue