since we can't ADL for std container iter, use different system
This introduces ranged_traits structure, which by default works for things defining .iter(), but also allows you to override it per type at later stage, which comes in handy for std containers. This is because we can't extend the std namespace in any way and we still need to be able to add iterable functionality to std containers even at later stage than iter() is defined.master
parent
0bf36b679a
commit
19226d51af
|
@ -13,19 +13,18 @@
|
|||
namespace ostd {
|
||||
|
||||
template<typename T, size_t N>
|
||||
inline PointerRange<T> iter(std::array<T, N> &v) {
|
||||
return PointerRange<T>{v.data(), N};
|
||||
}
|
||||
struct ranged_traits<std::array<T, N>> {
|
||||
static PointerRange<T> iter(std::array<T, N> &v) {
|
||||
return PointerRange<T>{v.data(), N};
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, size_t N>
|
||||
inline PointerRange<T const> iter(std::array<T, N> const &v) {
|
||||
return PointerRange<T const>{v.data(), N};
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
inline PointerRange<T const> citer(std::array<T, N> const &v) {
|
||||
return PointerRange<T const>{v.data(), N};
|
||||
}
|
||||
struct ranged_traits<std::array<T, N> const> {
|
||||
static PointerRange<T const> iter(std::array<T, N> const &v) {
|
||||
return PointerRange<T const>{v.data(), N};
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace ostd */
|
||||
|
||||
|
|
|
@ -741,19 +741,40 @@ inline auto zip(R1 &&r1, R &&...rr) {
|
|||
};
|
||||
}
|
||||
|
||||
template<typename C, typename = void>
|
||||
struct ranged_traits;
|
||||
|
||||
namespace detail {
|
||||
template<typename C>
|
||||
static True test_direct_iter(decltype(declval<C>().iter()) *);
|
||||
|
||||
template<typename>
|
||||
static False test_direct_iter(...);
|
||||
|
||||
template<typename C>
|
||||
constexpr bool direct_iter_test = decltype(test_direct_iter<C>(0))::value;
|
||||
}
|
||||
|
||||
template<typename C>
|
||||
struct ranged_traits<C, EnableIf<detail::direct_iter_test<C>>> {
|
||||
static auto iter(C &r) -> decltype(r.iter()) {
|
||||
return r.iter();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline auto iter(T &r) -> decltype(r.iter()) {
|
||||
return r.iter();
|
||||
inline auto iter(T &r) -> decltype(ranged_traits<T>::iter(r)) {
|
||||
return ranged_traits<T>::iter(r);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline auto iter(T const &r) -> decltype(r.iter()) {
|
||||
return r.iter();
|
||||
inline auto iter(T const &r) -> decltype(ranged_traits<T const>::iter(r)) {
|
||||
return ranged_traits<T const>::iter(r);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline auto citer(T const &r) -> decltype(r.iter()) {
|
||||
return r.iter();
|
||||
inline auto citer(T const &r) -> decltype(ranged_traits<T const>::iter(r)) {
|
||||
return ranged_traits<T const>::iter(r);
|
||||
}
|
||||
|
||||
template<
|
||||
|
|
|
@ -13,19 +13,18 @@
|
|||
namespace ostd {
|
||||
|
||||
template<typename T>
|
||||
inline PointerRange<T> iter(std::vector<T> &v) {
|
||||
return PointerRange<T>{v.data(), v.size()};
|
||||
}
|
||||
struct ranged_traits<std::vector<T>> {
|
||||
static PointerRange<T> iter(std::vector<T> &v) {
|
||||
return PointerRange<T>{v.data(), v.size()};
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline PointerRange<T const> iter(std::vector<T> const &v) {
|
||||
return PointerRange<T const>{v.data(), v.size()};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline PointerRange<T const> citer(std::vector<T> const &v) {
|
||||
return PointerRange<T const>{v.data(), v.size()};
|
||||
}
|
||||
struct ranged_traits<std::vector<T> const> {
|
||||
static PointerRange<T const> iter(std::vector<T> const &v) {
|
||||
return PointerRange<T const>{v.data(), v.size()};
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename R>
|
||||
inline std::vector<T> make_vector(R range) {
|
||||
|
|
Loading…
Reference in New Issue