forked from OctaForge/libostd
complete template param support for all ranged make_ funcs and ranged_traits
This commit is contained in:
parent
84f01c1286
commit
0842a24cd3
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
|
||||
#include "ostd/utility.hh"
|
||||
#include "ostd/range.hh"
|
||||
|
@ -246,33 +247,49 @@ inline bool starts_with(ConstCharRange a, ConstCharRange b) {
|
|||
return a.slice(0, b.size()) == b;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct ranged_traits<std::basic_string<T>> {
|
||||
static CharRangeBase<T> iter(std::basic_string<T> &v) {
|
||||
template<typename T, typename TR, typename A>
|
||||
struct ranged_traits<std::basic_string<T, TR, A>> {
|
||||
static CharRangeBase<T> iter(std::basic_string<T, TR, A> &v) {
|
||||
return CharRangeBase<T>{v.data(), v.size()};
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct ranged_traits<std::basic_string<T> const> {
|
||||
static CharRangeBase<T const> iter(std::basic_string<T> const &v) {
|
||||
template<typename T, typename TR, typename A>
|
||||
struct ranged_traits<std::basic_string<T, TR, A> const> {
|
||||
static CharRangeBase<T const> iter(std::basic_string<T, TR, A> const &v) {
|
||||
return CharRangeBase<T const>{v.data(), v.size()};
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename R>
|
||||
inline std::basic_string<T> make_string(R range) {
|
||||
/* TODO: specialize for contiguous ranges and matching value types */
|
||||
std::basic_string<T> ret;
|
||||
template<
|
||||
typename T, typename TR = std::char_traits<T>,
|
||||
typename A = std::allocator<T>, typename R
|
||||
>
|
||||
inline std::basic_string<T, TR, A> make_string(R range, A const &alloc = A{}) {
|
||||
std::basic_string<T, TR, A> ret{alloc};
|
||||
using C = RangeCategory<R>;
|
||||
if constexpr(std::is_convertible_v<C, FiniteRandomAccessRangeTag>) {
|
||||
/* finite random access or contiguous */
|
||||
auto h = range.half();
|
||||
ret.reserve(range.size());
|
||||
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;
|
||||
}
|
||||
|
||||
template<typename R>
|
||||
inline std::basic_string<RemoveCv<RangeValue<R>>> make_string(R range) {
|
||||
return make_string<RemoveCv<RangeValue<R>>>(std::move(range));
|
||||
template<
|
||||
typename R, typename TR = std::char_traits<RemoveCv<RangeValue<R>>>,
|
||||
typename A = std::allocator<RemoveCv<RangeValue<R>>>
|
||||
>
|
||||
inline std::basic_string<RemoveCv<RangeValue<R>>, TR, A> make_string(
|
||||
R range, A const &alloc = A{}
|
||||
) {
|
||||
return make_string<RemoveCv<RangeValue<R>>, TR, A>(std::move(range), alloc);
|
||||
}
|
||||
|
||||
/* string literals */
|
||||
|
|
|
@ -7,45 +7,72 @@
|
|||
#define OSTD_UNORDERED_MAP_HH
|
||||
|
||||
#include <unordered_map>
|
||||
#include <type_traits>
|
||||
|
||||
#include "ostd/range.hh"
|
||||
|
||||
namespace ostd {
|
||||
|
||||
template<typename K, typename T>
|
||||
struct ranged_traits<std::unordered_map<K, T>> {
|
||||
using Range = IteratorRange<typename std::unordered_map<K, T>::iterator>;
|
||||
static Range iter(std::unordered_map<K, T> &v) {
|
||||
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>
|
||||
struct ranged_traits<std::unordered_map<K, T> const> {
|
||||
using Range = IteratorRange<typename std::unordered_map<K, T>::const_iterator>;
|
||||
static Range iter(std::unordered_map<K, T> const &v) {
|
||||
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()};
|
||||
}
|
||||
};
|
||||
|
||||
template<typename K, typename T, typename R>
|
||||
inline std::unordered_map<K, T> make_unordered_map(R range) {
|
||||
std::unordered_map<K, T> ret;
|
||||
template<
|
||||
typename K, typename T, typename H = std::hash<K>,
|
||||
typename E = std::equal_to<K>,
|
||||
typename A = std::allocator<std::pair<K const, T>>, typename R
|
||||
>
|
||||
inline std::unordered_map<K, T> make_unordered_map(
|
||||
R range, size_t bcount = 1, H const &hash = H{},
|
||||
E const &kequal = E{}, A const &alloc = A{}
|
||||
) {
|
||||
std::unordered_map<K, T> ret{bcount, hash, kequal, alloc};
|
||||
using C = RangeCategory<R>;
|
||||
if constexpr(std::is_convertible_v<C, FiniteRandomAccessRangeTag>) {
|
||||
/* at least try to preallocate here... */
|
||||
ret.reserve(range.size());
|
||||
}
|
||||
for (; !range.empty(); range.pop_front()) {
|
||||
ret.emplace(range.front());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<typename R>
|
||||
template<
|
||||
typename R,
|
||||
typename H = std::hash<typename RangeValue<R>::first_type>,
|
||||
typename E = std::equal_to<typename RangeValue<R>::first_type>,
|
||||
typename A = std::allocator<std::pair<
|
||||
typename RangeValue<R>::first_type, typename RangeValue<R>::second_type
|
||||
>>
|
||||
>
|
||||
inline std::unordered_map<
|
||||
typename RangeValue<R>::first_type,
|
||||
typename RangeValue<R>::second_type
|
||||
> make_unordered_map(R &&range) {
|
||||
> make_unordered_map(
|
||||
R &&range, size_t bcount = 1, H const &hash = H{},
|
||||
E const &kequal = E{}, A const &alloc = A{}
|
||||
) {
|
||||
return make_unordered_map<
|
||||
typename RangeValue<R>::first_type,
|
||||
typename RangeValue<R>::second_type
|
||||
>(std::forward<R>(range));
|
||||
>(std::forward<R>(range), bcount, hash, kequal, alloc);
|
||||
}
|
||||
|
||||
} /* namespace ostd */
|
||||
|
|
|
@ -7,33 +7,35 @@
|
|||
#define OSTD_VECTOR_HH
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
#include "ostd/range.hh"
|
||||
|
||||
namespace ostd {
|
||||
|
||||
template<typename T>
|
||||
struct ranged_traits<std::vector<T>> {
|
||||
static PointerRange<T> iter(std::vector<T> &v) {
|
||||
template<typename T, typename A>
|
||||
struct ranged_traits<std::vector<T, A>> {
|
||||
static PointerRange<T> iter(std::vector<T, A> &v) {
|
||||
return PointerRange<T>{v.data(), v.size()};
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct ranged_traits<std::vector<T> const> {
|
||||
static PointerRange<T const> iter(std::vector<T> const &v) {
|
||||
template<typename T, typename A>
|
||||
struct ranged_traits<std::vector<T, A> const> {
|
||||
static PointerRange<T const> iter(std::vector<T, A> const &v) {
|
||||
return PointerRange<T const>{v.data(), v.size()};
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename R>
|
||||
inline std::vector<T> make_vector(R range) {
|
||||
std::vector<T> ret;
|
||||
template<typename T, typename A = std::allocator<T>, typename R>
|
||||
inline std::vector<T, A> make_vector(R range, A const &alloc = A{}) {
|
||||
std::vector<T, A> ret{alloc};
|
||||
using C = RangeCategory<R>;
|
||||
if constexpr(std::is_convertible_v<C, FiniteRandomAccessRangeTag>) {
|
||||
/* finite random access or contiguous */
|
||||
auto h = range.half();
|
||||
ret.reserve(range.size());
|
||||
ret.insert(ret.end(), h, h + range.size());
|
||||
} else {
|
||||
/* infinite random access and below */
|
||||
|
@ -44,9 +46,11 @@ inline std::vector<T> make_vector(R range) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
template<typename R>
|
||||
inline std::vector<RangeValue<R>> make_vector(R &&range) {
|
||||
return make_vector<RangeValue<R>>(std::forward<R>(range));
|
||||
template<typename R, typename A = std::allocator<RangeValue<R>>>
|
||||
inline std::vector<RangeValue<R>, A> make_vector(
|
||||
R &&range, A const &alloc = A{}
|
||||
) {
|
||||
return make_vector<RangeValue<R>, A>(std::forward<R>(range), alloc);
|
||||
}
|
||||
|
||||
} /* namespace ostd */
|
||||
|
|
Loading…
Reference in a new issue