forked from OctaForge/libostd
standard iter() for any std container type without ranged_traits
This commit is contained in:
parent
67cbcb71eb
commit
bd307bd52e
|
@ -1,6 +1,6 @@
|
||||||
#include <time.h>
|
#include <array>
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
#include <ostd/array.hh>
|
|
||||||
#include <ostd/range.hh>
|
#include <ostd/range.hh>
|
||||||
#include <ostd/io.hh>
|
#include <ostd/io.hh>
|
||||||
#include <ostd/algorithm.hh>
|
#include <ostd/algorithm.hh>
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
/* OctaSTD extensions for std::array.
|
|
||||||
*
|
|
||||||
* This file is part of OctaSTD. See COPYING.md for futher information.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef OSTD_ARRAY_HH
|
|
||||||
#define OSTD_ARRAY_HH
|
|
||||||
|
|
||||||
#include <array>
|
|
||||||
|
|
||||||
#include "ostd/range.hh"
|
|
||||||
|
|
||||||
namespace ostd {
|
|
||||||
|
|
||||||
template<typename T, size_t N>
|
|
||||||
struct ranged_traits<std::array<T, N>> {
|
|
||||||
static IteratorRange<T *> iter(std::array<T, N> &v) {
|
|
||||||
return IteratorRange<T *>{v.data(), v.data() + N};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T, size_t N>
|
|
||||||
struct ranged_traits<std::array<T, N> const> {
|
|
||||||
static IteratorRange<T const *> iter(std::array<T, N> const &v) {
|
|
||||||
return IteratorRange<T const *>{v.data(), v.data() + N};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace ostd */
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -23,7 +23,6 @@
|
||||||
#include "ostd/range.hh"
|
#include "ostd/range.hh"
|
||||||
#include "ostd/vector.hh"
|
#include "ostd/vector.hh"
|
||||||
#include "ostd/string.hh"
|
#include "ostd/string.hh"
|
||||||
#include "ostd/array.hh"
|
|
||||||
#include "ostd/algorithm.hh"
|
#include "ostd/algorithm.hh"
|
||||||
|
|
||||||
namespace ostd {
|
namespace ostd {
|
||||||
|
|
|
@ -815,9 +815,6 @@ inline auto zip(R1 &&r1, R &&...rr) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename C, typename = void>
|
|
||||||
struct ranged_traits;
|
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template<typename C>
|
template<typename C>
|
||||||
static std::true_type test_direct_iter(decltype(std::declval<C>().iter()) *);
|
static std::true_type test_direct_iter(decltype(std::declval<C>().iter()) *);
|
||||||
|
@ -827,14 +824,20 @@ namespace detail {
|
||||||
|
|
||||||
template<typename C>
|
template<typename C>
|
||||||
constexpr bool direct_iter_test = decltype(test_direct_iter<C>(0))::value;
|
constexpr bool direct_iter_test = decltype(test_direct_iter<C>(0))::value;
|
||||||
|
|
||||||
|
template<typename C, typename = void>
|
||||||
|
struct ranged_traits_core {};
|
||||||
|
|
||||||
|
template<typename C>
|
||||||
|
struct ranged_traits_core<C, std::enable_if_t<detail::direct_iter_test<C>>> {
|
||||||
|
static auto iter(C &r) -> decltype(r.iter()) {
|
||||||
|
return r.iter();
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename C>
|
template<typename C>
|
||||||
struct ranged_traits<C, std::enable_if_t<detail::direct_iter_test<C>>> {
|
struct ranged_traits: detail::ranged_traits_core<C> {};
|
||||||
static auto iter(C &r) -> decltype(r.iter()) {
|
|
||||||
return r.iter();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline auto iter(T &r) -> decltype(ranged_traits<T>::iter(r)) {
|
inline auto iter(T &r) -> decltype(ranged_traits<T>::iter(r)) {
|
||||||
|
@ -1842,6 +1845,36 @@ inline IteratorRange<T *> iter(T *a, size_t b) {
|
||||||
return IteratorRange<T *>(a, a + b);
|
return IteratorRange<T *>(a, a + b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* iter on standard containers */
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
template<typename C>
|
||||||
|
static std::true_type test_std_iter(
|
||||||
|
decltype(std::begin(std::declval<C>())) *,
|
||||||
|
decltype(std::end(std::declval<C>())) *
|
||||||
|
);
|
||||||
|
|
||||||
|
template<typename>
|
||||||
|
static std::false_type test_std_iter(...);
|
||||||
|
|
||||||
|
template<typename C>
|
||||||
|
constexpr bool std_iter_test = decltype(test_std_iter<C>(0, 0))::value;
|
||||||
|
|
||||||
|
template<typename C>
|
||||||
|
struct ranged_traits_core<C, std::enable_if_t<
|
||||||
|
detail::std_iter_test<C> && !detail::direct_iter_test<C>
|
||||||
|
>> {
|
||||||
|
using range_type = std::conditional_t<
|
||||||
|
std::is_const_v<C>,
|
||||||
|
IteratorRange<typename C::const_iterator>,
|
||||||
|
IteratorRange<typename C::iterator>
|
||||||
|
>;
|
||||||
|
static range_type iter(C &r) {
|
||||||
|
return range_type{r.begin(), r.end()};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
} /* namespace ostd */
|
} /* namespace ostd */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -13,26 +13,6 @@
|
||||||
|
|
||||||
namespace ostd {
|
namespace ostd {
|
||||||
|
|
||||||
template<typename K, typename T, typename H, typename E, typename A>
|
|
||||||
struct ranged_traits<std::unordered_map<K, T, H, E, A>> {
|
|
||||||
using Range = IteratorRange<
|
|
||||||
typename std::unordered_map<K, T, H, E, A>::iterator
|
|
||||||
>;
|
|
||||||
static Range iter(std::unordered_map<K, T, H, E, A> &v) {
|
|
||||||
return Range{v.begin(), v.end()};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename K, typename T, typename H, typename E, typename A>
|
|
||||||
struct ranged_traits<std::unordered_map<K, T, H, E, A> const> {
|
|
||||||
using Range = IteratorRange<
|
|
||||||
typename std::unordered_map<K, T, H, E, A>::const_iterator
|
|
||||||
>;
|
|
||||||
static Range iter(std::unordered_map<K, T, H, E, A> const &v) {
|
|
||||||
return Range{v.cbegin(), v.cend()};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
std::integral_constant<
|
std::integral_constant<
|
||||||
|
|
|
@ -14,20 +14,6 @@
|
||||||
|
|
||||||
namespace ostd {
|
namespace ostd {
|
||||||
|
|
||||||
template<typename T, typename A>
|
|
||||||
struct ranged_traits<std::vector<T, A>> {
|
|
||||||
static IteratorRange<T *> iter(std::vector<T, A> &v) {
|
|
||||||
return IteratorRange<T *>{v.data(), v.data() + v.size()};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T, typename A>
|
|
||||||
struct ranged_traits<std::vector<T, A> const> {
|
|
||||||
static IteratorRange<T const *> iter(std::vector<T, A> const &v) {
|
|
||||||
return IteratorRange<T const *>{v.data(), v.data() + v.size()};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T, typename A = std::allocator<T>, typename R>
|
template<typename T, typename A = std::allocator<T>, typename R>
|
||||||
inline std::vector<T, A> make_vector(R range, A const &alloc = A{}) {
|
inline std::vector<T, A> make_vector(R range, A const &alloc = A{}) {
|
||||||
std::vector<T, A> ret{alloc};
|
std::vector<T, A> ret{alloc};
|
||||||
|
|
Loading…
Reference in a new issue