range system fixes, add iterator types to RangeHalf, optimize make_vector(R)

master
Daniel Kolesa 2017-02-01 18:28:57 +01:00
parent e0072773e1
commit 077835e4b6
2 changed files with 50 additions and 6 deletions

View File

@ -322,6 +322,34 @@ namespace detail {
};
}
namespace detail {
template<typename>
struct RangeIteratorTag {
/* better range types all become random access iterators */
using Type = std::random_access_iterator_tag;
};
template<>
struct RangeIteratorTag<InputRangeTag> {
using Type = std::input_iterator_tag;
};
template<>
struct RangeIteratorTag<OutputRangeTag> {
using Type = std::output_iterator_tag;
};
template<>
struct RangeIteratorTag<ForwardRangeTag> {
using Type = std::forward_iterator_tag;
};
template<>
struct RangeIteratorTag<BidirectionalRangeTag> {
using Type = std::bidirectional_iterator_tag;
};
}
template<typename T>
struct RangeHalf {
private:
@ -329,6 +357,12 @@ private:
public:
using Range = T;
using iterator_category = typename detail::RangeIteratorTag<T>::Type;
using value_type = RangeValue<T>;
using difference_type = RangeDifference<T>;
using pointer = RangeValue<T> *;
using reference = RangeReference<T>;
RangeHalf() = delete;
RangeHalf(T const &range): p_range(range) {}
@ -387,7 +421,7 @@ public:
/* iterator like interface */
RangeReference<T> operator*() const {
return get();
return p_range.front();
}
RangeReference<T> operator[](RangeSize<T> idx) const {
@ -445,7 +479,9 @@ public:
};
template<typename R>
inline RangeDifference<R> operator-(R const &lhs, R const &rhs) {
inline RangeDifference<R> operator-(
RangeHalf<R> const &lhs, RangeHalf<R> const &rhs
) {
return rhs.distance(lhs);
}
@ -612,7 +648,7 @@ struct InputRange {
* this is sometimes convenient as it can be used within expressions */
Reference operator*() const {
return static_cast<B const *>(this)->front();
return std::forward<Reference>(static_cast<B const *>(this)->front());
}
B &operator++() {

View File

@ -7,6 +7,7 @@
#define OSTD_VECTOR_HH
#include <vector>
#include <type_traits>
#include "ostd/range.hh"
@ -28,10 +29,17 @@ struct ranged_traits<std::vector<T> const> {
template<typename T, typename R>
inline std::vector<T> make_vector(R range) {
/* TODO: specialize for contiguous ranges and matching value types */
std::vector<T> ret;
for (; !range.empty(); range.pop_front()) {
ret.push_back(range.front());
using C = RangeCategory<R>;
if constexpr(std::is_convertible_v<C, FiniteRandomAccessRangeTag>) {
/* finite random access or contiguous */
auto h = range.half();
ret.insert(ret.end(), h, h + range.size());
} else {
/* infinite random access and below */
for (; !range.empty(); range.pop_front()) {
ret.push_back(range.front());
}
}
return ret;
}